import * as puppeteer from "puppeteer";
import config from "../../config";
import { Rule } from "../rule";
import Word from "../word";
import Action from "./action";

export default abstract class TargetBasedAction extends Action {

    public selector: string;

    constructor(word: Word, rule: Rule, selector: string) {
        super(word, rule);
        this.selector = selector;
    }

    public exec(page: puppeteer.Page): Promise<any> {
        return this.selectTarget(page)
        .then((target) => this.execOnTarget(page, target));
    }

    public abstract execOnTarget(page: puppeteer.Page, target: puppeteer.ElementHandle): Promise<any>;

    public selectTarget(page: puppeteer.Page): Promise<puppeteer.ElementHandle> {
        return page.waitFor(this.selector, {timeout: config.TIMEOUT})
        .then(() =>
            page.$$(this.selector).then((elements) => {
                if (! this.rule) {
                    return elements[0];
                }
                switch (this.rule.suffix) {
                    case undefined:
                        return elements[0];
                    case "index":
                        return this.getElementForIndex(elements);
                    case "value":
                        if (config.ENABLE_VALUE_SPECIFIC_SUFFIX) {
                            return this.getElementForValue(elements);
                        } else {
                            return elements[0];
                        }
                    case "innerText":
                        return this.getElementForInnerText(elements);
                    default:
                        console.log("suffix is ", this.rule.suffix, " taking default value");
                        return elements[0];
                }
            }),
        );
    }

    public getElementForIndex(elements: puppeteer.ElementHandle[]): Promise<puppeteer.ElementHandle> {
        const index = this.word.suffix;
        if (elements[index]) {
            return Promise.resolve(elements[index]);
        } else {
            console.log("no element found for index ", index, " picking first one");
            return Promise.resolve(elements[0]);
        }
    }

    public async getElementForValue(elements: puppeteer.ElementHandle[]): Promise<puppeteer.ElementHandle> {
        const value = this.word.suffix;
        for (const element of elements) {
            const elemValue = await element.evaluate((elem) => {
                return elem.value;
            });
            if (elemValue === value) {
                return element;
            }
        }
        console.log("no element found for value ", value, " picking first one");
        return elements[0];
    }

    public async getElementForInnerText(elements: puppeteer.ElementHandle[]): Promise<puppeteer.ElementHandle> {
        const innerText = this.word.suffix;
        for (const element of elements) {
            const elemValue = await element.evaluate((elem) => {
                return elem.innerText;
            });
            if (elemValue === innerText) {
                return element;
            }
        }
        console.log("no element found for innerText ", innerText, " picking first one");
        return elements[0];
    }
}
