import BrowserService from "./BrowserService";
import Window from "./Window";

export default class WindowManager {
    private _browserService : BrowserService;
    private _connectedWindow : Window;
    private _lastCreatedWindow : Window;
    private _onWindowRemovedListener: Array<(windowId : number) => void>;

    constructor(browserService : BrowserService) {
        this._browserService = browserService;
        this._connectedWindow = undefined;
        this._lastCreatedWindow = undefined;
        this._onWindowRemovedListener = [];
        this.attachHandlers();
    }

    addOnWindoRemovedListener(listener : (windowId : number) => void) {
        this._onWindowRemovedListener.push(listener);
    }

    createConnectedWindow(url?:string) : Promise<void> {
        console.log(this._connectedWindow);
        return this._browserService.createWindow(url)
            .then((id) => {
                if (this._lastCreatedWindow?.id !== id) {
                    this._connectedWindow = new Window(id);
                    console.log(this._connectedWindow);
                    this._browserService.getTabIdListOfWindow(this._connectedWindow.id)
                    .then((tabIdList) => {
                        if (tabIdList) {
                            tabIdList.forEach(tabId => this._connectedWindow.addTab(tabId));
                        }
                    })
                    .catch(() => {
                    })
                } else {
                    this._connectedWindow = this._lastCreatedWindow;
                }
            })
    }

    connectToExistingWindow() : Promise<void> {
        return this._browserService.getCurrentWindow()
            .then(({windowId,tabsId}) => {
                if (this._connectedWindow && this._connectedWindow.id === windowId) {
                    return;
                }
                this._connectedWindow = new Window(windowId);
                if (tabsId) {
                    tabsId.forEach(tabId => {
                        this._connectedWindow.addTab(tabId);
                        this.connectTab(tabId);
                    });
                }
            })
            .catch(() => {
                console.error("Failed to getCurrentCurrent");
            })
    }

    removeConnectedWindow() : Promise<void> {
        let connectedWindowId = this.getConnectedWindowId();
        if (connectedWindowId) {
            return this._browserService.closeWindow(connectedWindowId)
                .then((_) => {
                    this._connectedWindow = undefined;
                })
        } else {
            return Promise.resolve();
        }
    }

    reloadConnectedWindow(url?:string) : Promise<void> {
        return this._browserService.restartWindow(this._connectedWindow.id, url);
    }

    getConnectedWindowId() : number {
        return this._connectedWindow?.id;
    }

    getConnectedTabIds() : Array<number> {
        if (this._connectedWindow) {
            return this._connectedWindow.getConnectedTabIds();
        } else {
            return [];
        }
    }

    getActivatedTabId() : number | undefined {
        return this._connectedWindow?.getActivatedTabId();
    }

    connectTab(tabId) {
        if (this._connectedWindow) {
            if (this._connectedWindow.hasTab(tabId)) {
                this._browserService.runScript(tabId)
                    .then((isRunning) => {
                        if (isRunning) {
                            this._connectedWindow.connectTab(tabId);
                        }
                    })
            }
        }
    }

    private attachHandlers() {
        this._browserService.attachWindowCreatedHandler(this.onWindowCreated.bind(this));
        this._browserService.attachWindowRemovedHandler(this.onWindowRemoved.bind(this));
        this._browserService.attachTabCreatedHandler(this.onTabCreated.bind(this));
        this._browserService.attachTabRemovedHandler(this.onTabRemoved.bind(this));
        this._browserService.attachTabDetachedHandler(this.onTabDetached.bind(this));
        this._browserService.attachTabAttachedHandler(this.onTabAttached.bind(this));
        this._browserService.attachTabActivatedHandler(this.onTabActivated.bind(this));
        this._browserService.attachOnDomLoadedHandler(this.onNavigationDOMLoaded.bind(this));
        this._browserService.attachOnCommittedHandler(this.onNavigationCommitted.bind(this));
    }

    private onWindowCreated(windowId: number) {
        if (this._connectedWindow === undefined) {
            //console.log('window created:',windowId);
            this._lastCreatedWindow = new Window(windowId);
            let window = this._lastCreatedWindow;
            let id = this._lastCreatedWindow.id;
            this._browserService.getCurrentWindow()
            .then(({windowId,tabsId}) => {
                if (windowId === id) {
                    if (tabsId) {
                        tabsId.forEach(tabId => window.addTab(tabId));
                    }
                }
            })
            .catch(() => {

            })
        }
    }

    private onWindowRemoved(windowId: number) {
        if (windowId === this._connectedWindow?.id) {
            this._onWindowRemovedListener.forEach(listener => listener(windowId));
            this._connectedWindow = undefined;
        } else {
            if (windowId === this._lastCreatedWindow?.id) {
                this._lastCreatedWindow = undefined;
            } 
        }
    }

    private onTabCreated(tabId: number, windowId: number) {
        //console.log(`tab ${tabId} created to window ${windowId}`);
        if (windowId === this._connectedWindow?.id) {
            //console.log(`tab ${tabId} added to window ${windowId}`);
            this._connectedWindow.addTab(tabId);
        } else {
            if (windowId === this._lastCreatedWindow?.id) {
                //console.log(`tab ${tabId} added to window ${windowId}`);
                this._lastCreatedWindow.addTab(tabId);
            }
        }
    }

    private onTabRemoved(tabId: number, windowId:number) {
        if (windowId === this._connectedWindow?.id) {
            this._connectedWindow.removeTab(tabId);
        } else {
            if (windowId === this._lastCreatedWindow?.id) {
                this._lastCreatedWindow.removeTab(tabId);
            }
        }
    }

    private onTabDetached(tabId: number, windowId:number) {
        if (windowId === this._connectedWindow?.id) {
            this._connectedWindow.removeTab(tabId);
        } else {
            if (windowId === this._lastCreatedWindow?.id) {
                this._lastCreatedWindow.removeTab(tabId);
            }
        }
    }

    private onTabAttached(tabId: number, windowId:number) {
        if (windowId === this._connectedWindow?.id) {
            this._connectedWindow.addTab(tabId);
        } else {
            if (windowId === this._lastCreatedWindow?.id) {
                this._lastCreatedWindow.addTab(tabId);
            }
        }
    }

    private onTabActivated(tabId: number, windowId: number) {
        if (windowId === this._connectedWindow?.id) {
            this._connectedWindow.activateTab(tabId);
        } else {
            if (windowId === this._lastCreatedWindow?.id) {
                this._lastCreatedWindow.activateTab(tabId);
            }
        }
    }

    private onNavigationDOMLoaded(tabId: number) {
        this.connectTab(tabId);
    }

    private onNavigationCommitted(tabId: number) {
        if (this._connectedWindow?.hasTab(tabId)) {
            //console.log('Committed');  
        }
    }

    
}