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> {
        if (this._connectedWindow?.id)  {
            throw new Error("cannot createConnectedWindow, it already exists");
        }
        return this._browserService.createWindow(url)
            .then((id) => {
                if (this._lastCreatedWindow?.id !== id) {
                    this._connectedWindow = new Window(id);
                } else {
                    this._connectedWindow = this._lastCreatedWindow;
                }
                //console.log(`windows is managed`);
            })
    }

    connectToExistingWindow(url?:string) : Promise<void> {
        if (this._connectedWindow?.id) {
            throw new Error("cannot createConnectedWindow, it already exists");
        }
        return this._browserService.getCurrentWidow()
            .then((ids) => {
                if (this._lastCreatedWindow?.id !== ids.windowId) {
                    this._connectedWindow = new Window(ids.windowId);
                }
            })
    }

    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;
    }

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

    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) {
            this._lastCreatedWindow = new Window(windowId);
        }
    }

    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) {
        if (windowId === this._connectedWindow?.id) {
            this._connectedWindow.addTab(tabId);
        } else {
            if (windowId === this._lastCreatedWindow?.id) {
                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.addTab(tabId);
            }
        }
    }

    private onNavigationDOMLoaded(tabId: number) {
        if (this._connectedWindow) {
            //console.log('DOMloaded');
            if (this._connectedWindow.hasTab(tabId)) {
                //console.log('in tab');
                this._browserService.runScript(tabId)
                    .then((isRunning) => {
                        //console.log('is running:',isRunning);
                        if (isRunning) {
                            this._connectedWindow.connectTab(tabId);
                        }
                    })
            }
        }
    }

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

    
}