import { autocomplete_request } from "./autocomplete_request";
import { create_request } from "./create_request";
import { import_process_fail } from "./import_process_fail.js";
import { product_get_request } from "./product_get_request.js";

export class import_loop {
    #content;
    #on_autocomplete;
    #on_create;
    #on_single_fail;
    #on_skip;
    #on_single_success;
    #finally;

    on_autocomplete(target) {
        this.#on_autocomplete = target;
        return this;
    }

    on_create(target) {
        this.#on_create = target;
        return this;
    }

    on_single_fail(target) {
        this.#on_single_fail = target;
        return this;
    }

    on_skip(target) {
        this.#on_skip = target;
        return this;
    }

    on_single_success(target) {
        this.#on_single_success = target;
        return this;
    }

    finally(target) {
        this.#finally = target;
        return this;
    }

    constructor(dataset) {
        this.#content = dataset;
        this.#on_autocomplete = null;
        this.#on_create = null;
        this.#on_single_fail = null;
        this.#on_skip = null;
        this.#on_single_success = null;
        this.#finally = null;
    }

    async #autocomplete(target) {
        if (this.#on_autocomplete !== null) {
            try {
                this.#on_autocomplete(target);
            } catch (error) {
                console.log(error);
            }
        }

        const request = new autocomplete_request(target.barcode);
        const response = await request.connect();

        if (!response.result) {
            throw new Error(response.cause);
        }

        const found = response.found;
        target.description = found.description;

        if (found.image.length === 0) {
            throw new Error("Image for " + target.barcode + " not found.");
        }

        return new create_request(target, found.image);
    }

    async process() {
        for (const count of this.#content) {
            try {
                await this.#create(count);
            } catch(error) {
                if (this.#on_single_fail !== null) {
                    try {
                        const fail = new import_process_fail(count, error);
                        this.#on_single_fail(fail);
                    } catch (error) {
                        console.log(error);
                    }
                }
            }
        }

        if (this.#finally !== null) {
            try {
                this.#finally();
            } catch (error) {
                console.log(error);
            }
        }

        return this;
    }

    async #exists(target) {
        const request = new product_get_request(target.barcode);
        const response = await request.connect();

        return response.product !== null;
    }

    async #create(target) {
        if (await this.#exists(target)) {
            try {
                const result = new import_process_fail(target, null);
                this.#on_skip(result);
            } catch (error) {
                console.log(error);
            }

            return;
        }

        const request = await this.#autocomplete(target);

        if (this.on_create !== null) {
            try {
                this.#on_create(target);
            } catch (error) {
                console.log(error);
            }
        }

        const response = await request.connect();

        if (!response.result) {
            throw new Error(response.cause);
        }

        if (this.#on_single_success !== null) {
            try {
                this.#on_single_success(target);
            } catch (error) {
                console.log(error);
            }
        }
    }
}