
import BrowserService from "../domain/BrowserService";
import { getWindowById, updateWindowById, createWindow, getCurrentWindow, removeWindowById, executeTabScript, removeTabs, createTab, takeScreenshot } from "./ChromePromise";
import ChromeWindowOption from "./ChromeWindowOption";
const DEFAULT_WINDOW_OPTIONS = {url:'https://www.aifex.fr'};

export default class ChromeBrowserService implements BrowserService {

    recorder : MediaRecorder;
    stream : MediaStream;
    recordedChunks : Array<Blob>;

    constructor() {
        this.recorder = undefined;
        this.stream = undefined;
        this.recordedChunks = [];
    }
    
    getExtensionVesion() {
        return chrome.runtime.getManifest().version
    }


    createWindow(url?:string): Promise<number> {
        const options = Object.assign(DEFAULT_WINDOW_OPTIONS, {url});
        const chromeOptions = new ChromeWindowOption(options);
        return createWindow(chromeOptions)
            .then( window => {
                //console.log('managed window', window.id);
                return window.id;
            })
    }

    getCurrentWidow(): Promise<{windowId:number, tabsId?:number[]}> {
        return getCurrentWindow()
            .then( window => {
                //console.log('managed window', window.id);
                return {
                    windowId:window.id,
                    tabsId: window.tabs?.map(tab => tab.id)
                }
            })
    }

    drawAttentionToWindow(windowId: number): Promise<void> {
        return getWindowById(windowId)
            .then( _window => {
                return updateWindowById(windowId, {drawAttention: true,focused: true});
            })
    }


    closeWindow(windowId: number):Promise<void> {
        //console.log('managaedWindow will be closed');
        return removeWindowById(windowId);
    }

    runScript(tabId: number): Promise<boolean> {
        return executeTabScript(tabId)
    }

    restartWindow(windowId: number, url?: string): Promise<void> {
        let tabIds;
        return getWindowById(windowId)
            .then((window) => {
                return window.tabs
            })
            .then((tabs) => {
                tabIds = tabs.map(tab=>tab.id)
                return createTab({windowId, index:0, url});
            })
            .then(() => {
                return removeTabs(tabIds);
            })
    }

   
    takeScreenshot(): Promise<string> {
        return takeScreenshot();
    }

    /*
    startTabRecording() : Promise<void> {
        this.recordedChunks = [];
        this.recorder = undefined;
        return new Promise((res, rej) => {
            chrome.tabs.query({active: true, currentWindow: true}, tabs => {
                if (tabs.find( tab => this.tabIdsList.includes(tab.id))) {
                    chrome.tabCapture.capture({
                        audio : false,
                        video : true
                    }, (stream: MediaStream) => {
                        if (stream === null) {
                            const error = chrome.runtime.lastError;
                            rej(error);
                        } else {
                            this.stream = stream;
                            const options = {mimeType: 'video/webm; codecs=vp9'};
                            this.recorder = new MediaRecorder(stream, options);
                            this.recorder.ondataavailable = event => {
                                    console.log('video event:',event);
                                    if (event.data.size > 0) {
                                        console.log('push on recordedChunks');
                                        this.recordedChunks.push(event.data);
                                    }
                                };
                            this.recorder.onerror = error => {
                                console.log('error',error);
                            }
                            try {
                                this.recorder.start();
                                console.log('recorder started');
                                res();
                            } catch (error) {
                                rej(error);
                            }
                        }
                    });
                } else {
                    rej('cannot record a tab that is not monitored by AIFEX');
                }
            })
            
        })
    }

    stopTabRecording() : Promise<void> {
        return new Promise((res, rej) => {
            if (this.recorder === undefined || this.recorder.state !== 'recording') {
                res();
                return;
            }
            try {
                this.recorder.ondataavailable = event => {
                    if (event.data.size > 0) {
                        console.log('push on recordedChunks');
                        this.recordedChunks.push(event.data);
                        this.stream.getVideoTracks().forEach((track: MediaStreamTrack) => {
                            track.stop();
                            
                        });
                    }
                    console.log('video is stoped:',event);
                    res();
                };
                this.recorder.stop();
            } catch (error) {
                rej(error);
            }
        })
    }

    getTadRecordedMedia() : Blob {
        return new Blob(this.recordedChunks, {type : 'video/webm'});
    }
    */

    attachWindowCreatedHandler( handler : (windowId:number) => void) {
        chrome.windows.onCreated.addListener((window) => {
            handler(window.id);
        })
    }

    attachWindowRemovedHandler(handler: (windowId: number) => void) {
        chrome.windows.onRemoved.addListener(handler);
    }
    
    attachTabCreatedHandler(handler : (tabId:number, windowId:number) => void) {
        chrome.tabs.onCreated.addListener((tab) => {
            handler(tab.id, tab.windowId);
        })
    }
    
    attachTabRemovedHandler(handler : (tabId:number, windowId:number) => void) {
        chrome.tabs.onRemoved.addListener( (tabId, removeInfo) => {
            handler(tabId, removeInfo.windowId);
        });
    }

    attachTabDetachedHandler(handler: (tabId: number, windowId: number) => void) {
        chrome.tabs.onDetached.addListener( (tabId , detachInfo) => {
            handler(tabId, detachInfo.oldWindowId);
        })
    }
    
    attachTabAttachedHandler(handler: (tabId: number, windowId: number) => void) {
        chrome.tabs.onAttached.addListener((tabId, attachInfo) => {
            handler(tabId, attachInfo.newWindowId);
        })
    }
    
    attachTabActivatedHandler(handler: (tabId: number, windowId: number) => void) {
        chrome.tabs.onActivated.addListener((activeInfo) => {
            handler(activeInfo.tabId, activeInfo.windowId);
        })
    }

    attachOnDomLoadedHandler( handler : (tabId:number) => void) {
        chrome.webNavigation.onDOMContentLoaded.addListener(details => {
            const NAVIGATION_OCCURS_IN_TOP_FRAME = 0;
            if (details.frameId === NAVIGATION_OCCURS_IN_TOP_FRAME) {
                handler(details.tabId);
            }
        })
    }

    attachOnCommittedHandler( handler : (tabId:number) => void) {
        chrome.webNavigation.onDOMContentLoaded.addListener(details => {
            const NAVIGATION_OCCURS_IN_TOP_FRAME = 0;
            if (details.frameId === NAVIGATION_OCCURS_IN_TOP_FRAME) {
                handler(details.tabId);
            }
        })
    }

}
