import State from "../domain/State";
import ActionProbabilityMap from "../domain/ActionProbabilityMap";
import Comment from "../domain/Comment";
import Action from "../domain/Action";
import ExplorationEvaluation from "../domain/ExplorationEvaluation";
import BackgroundService from "../domain/BackgroundService";
import { Step } from "../domain/ExplorationEvaluation";
import Question from "../domain/Question";


export default class ChromeBackgroundMessageService  implements BackgroundService{

    getState(): Promise<State> {
        return new Promise((resolve, reject) => {
            chrome.runtime.sendMessage({
                kind: 'getStateForTabScript'
            }, {}, (data: {
                commentsUp: string[],
                displayUserView: boolean,
                isActive: boolean,
                isRecording: boolean,
                popupCommentPosition: {x: string, y: string},
                webSite: any
            }) => {
                const error = chrome.runtime.lastError;
                if (error) {
                    return reject(error);
                } else {
                    let isActive = data.isRecording ? true : false;
                    let commentsUp = []
                    if (data.commentsUp && Array.isArray(data.commentsUp)) {
                        commentsUp = data.commentsUp.map((commentText) => Comment.parseComment(commentText));
                    }
                    const state = new State(
                        commentsUp,
                        data.displayUserView,
                        isActive, 
                        data.webSite, 
                        data.popupCommentPosition);
                    return resolve(state)
                }
            });
        })
    }

    getProbabilityMap(): Promise<ActionProbabilityMap> {
        return new Promise((resolve, reject) => {
            chrome.runtime.sendMessage({
                kind: 'getProbabilities'
            }, {}, data => {
                const error = chrome.runtime.lastError;
                if (error) {
                    return reject(error);
                }
                if (data?.probabilityMap) {
                    return resolve(new ActionProbabilityMap(data.probabilityMap)); 
                } else {
                    return resolve(new ActionProbabilityMap(new Map()));
                }
                
            })
        })   
    }

    getCommentList(): Promise<Comment[]> {
        return new Promise((resolve, reject) => {
            chrome.runtime.sendMessage({
                kind: 'getComments'
            }, {}, data => {
                const error = chrome.runtime.lastError;
                if (error) {
                    return reject(error);
                }
                const comments = []
                if (data?.commentDistributionList) {
                    let commentDistributionList = data.commentDistributionList;
                    for (const commentData of commentDistributionList) {
                        const comment = Comment.parseComment(commentData.note);
                        for (const distribution of commentData.distributions) {
                            comment.addDistribution(distribution.noteOccurence, distribution.contextOccurence, distribution.context.map(actionText => Action.parseAction(actionText)));
                        }
                        comments.push(comment);
                    }
                }
                return resolve(comments);
            })
        })
    }

    getExplorationEvaluation(): Promise<ExplorationEvaluation | null> {
        return new Promise((resolve, reject) => {
            chrome.runtime.sendMessage({
                kind: 'getEvaluation'
            }, {}, (data: {
                validatedStepList: {name: string, expression: string}[];
                notValidatedStepList: {name: string, expression: string}[];
                enteringInteractionList: string[];
                continuingActionList: string[];
                finishingInteractionList: string[];
                questionList: string[];
            }) => {
                const error = chrome.runtime.lastError;
                if (error) {
                    return reject(error);
                }
                if (!data) {
                    return resolve(null);
                }
                resolve(new ExplorationEvaluation(
                    data.validatedStepList.map(stepData => new Step(stepData.name, stepData.expression)), 
                    data.notValidatedStepList.map(stepData => new Step(stepData.name, stepData.expression)), 
                    data.enteringInteractionList.map(action => Action.parseAction(action)),
                    data.continuingActionList.map(action => Action.parseAction(action)),
                    data.finishingInteractionList.map(action => Action.parseAction(action)),
                    data.questionList.map(text => new Question(text))
                ));
            })
        })
    }

    setUserViewPosition(newPosition: {x: number, y:number}) {
        return new Promise((resolve, reject) => {
            chrome.runtime.sendMessage({
                kind: 'setPopupCommentPosition',
                popupCommentPosition: newPosition
              }, {}, () => {
                const error = chrome.runtime.lastError;
                if (error) {
                    return reject(error);
                } else {
                    return resolve();
                }
            });
        })
    }

    upComment(comment: Comment) {
        return new Promise((resolve, reject) => {        
            chrome.runtime.sendMessage({
                kind: 'upComment',
                type: comment.type,
                value: comment.note
            }, {}, () => {
                const error = chrome.runtime.lastError;
                if (error) {
                    return reject(error);
                } else {
                    return resolve();
                }
            });
        })
    }

    sendAction(action: Action): Promise<void> {
        return new Promise((resolve, reject) => {        
            chrome.runtime.sendMessage({
                action,
                kind: 'pushAction'
            }, {}, () => {
                const error = chrome.runtime.lastError;
                    if (error) {
                        return reject(error);
                    } else {
                        return resolve();
                    }
            })
        })
    }

    sendAnswer(question: Question, value: boolean) {
        return new Promise((resolve, reject) => {        
            //console.log("sending message", question, value)
            chrome.runtime.sendMessage({
                question,
                value,
                kind: 'pushAnswer'
            }, {}, () => {
                const error = chrome.runtime.lastError;
                    if (error) {
                        console.log(error)
                        return reject(error);
                    } else {
                        return resolve();
                    }
            })
        })    }


}

    