import Action from "../Action";
import Mapping from "../Mapping";
import Session from "../Session";

// Value Object
export default class PuppeteerActionMapper {

    public static getActionCode(action: Action, session: Session, mapping: Mapping, options): string {

        if (action.kind === "start") {
            return makeStartAction(session.baseURL, options);
        }
        if (action.kind === "end") {
            return "";
        }

        if (mapping === undefined) {
            throw new Error("No mapping found");
        }
        switch (mapping.match.event) {
            case "click":
                return makeClickAction(mapping.match.selector, options);
            case "keyup":
                if (mapping.output.suffix === "value") {
                    return makeTypeAction(mapping.match.selector, action.value, options) + makeKeyupAction(mapping.match.code, options);
                } else {
                    return makeKeyupAction(mapping.match.code, options);
                }
            case "mouseover":
                return makeMouseOverAction(mapping.match.selector, options);
            case "change":
                return makeChangeAction(mapping.match.selector, action.value, options);
            default:
                throw new Error(`NotHandledEventTypeError Event type ${mapping.match.event} is not handled`);
        }
    }
}

function makeStartAction(url: string, options: any): string {
    return `await page.goto("${url}", {waitUntil: 'load'});`;
}

function makeClickAction(selector: string, options: any): string {
    return `await page.waitFor("${selector}");
    await page.click("${selector}");`;
}

function makeKeyupAction(keyCode, options: any): string {
    return `
    element = await page.evaluateHandle(() => document.activeElement);
    await element.asElement().press("${keyCode}");
    `;
}

function makeTypeAction(selector, text, options: any): string {
    return `await page.waitFor("${selector}");
    await page.type("${selector}", "${text}");`;
}

function makeChangeAction(selector, value, options: any): string {
    return `
    await page.waitFor('${selector}');
    element = await page.$('${selector}');
    tag = await element.evaluate((elem) => elem.tagName);
    if (tag === 'SELECT') {
        await element.select('${value}')
    }
    else {
        await element.type('${value}')
    }`;
}

function makeMouseOverAction(selector, options: any): string {
    return `
    await page.waitFor('${selector}');
    element = await page.$('${selector}');
    await element.hover()`;
}
