/**
 * This module should contain warnings subsystem.
 * First idea - there should be either definitive list of available warnings,
 * or defined as some json logic leading to the warning message(s), similar way how FillExtData works.
 * Second - resources indicator should be separate component
 */

import {item_occupied_counters, resource_counters} from "./count_resources";
import {useShopStore} from "./shop_store";

export const Levels = {
    "reminder": {priority: 1, icon: '/images/shop/icon-reminder.svg', color: "#0d3547"},
    "warning": {priority: 2, icon: '/images/shop/icon-warning.svg', color: "#c75e5e"},
}

const find_in_counters = (counters, name) => {
    return counters.find((element) => element.name === name)
}

const find_previous_source = (data, index, source) => {
    return data.slice(0, index).find((element) => {
        return element.resources && find_in_counters(element.resources, source)
    })
}

const find_next_source_index = (data, index, source) => {
    return data.slice(index + 1).findIndex((element) => {
        return element.resources && find_in_counters(element.resources, source)
    }) + index + 1
}

const not_enough_resource_trigger = (name) => {
    return (_data, _index, counters) => {
        const resource = find_in_counters(counters, name);
        return resource.occupied > resource.max;
    }
}

const no_source_trigger = (name) => {
    return (data, index, _counters) => {
        const occupied = item_occupied_counters[name](data[index]);
        if (occupied > 0)
            return !find_previous_source(data, index, name);
        return false;
    }
}

const wiring_constraint = (name) => {
    return (data, index, _counters) => {
        const next = find_next_source_index(data, index, name);
        return next - index === 1;
    }
}

const Types = {
    "eem_resource": {
        level: "warning",
        trigger: not_enough_resource_trigger("eem"),
        message: "Insufficient EEM connectors"
    },
    "no_eem_source": {
        level: "warning",
        trigger: no_source_trigger("eem"),
        message: 'This card needs a card that provides a EEM connector (e.g. Kasli) at its left.'
    },
    "idc_resource": {
        level: "warning",
        trigger: not_enough_resource_trigger("idc"),
        message: "Insufficient IDC connectors."
    },
    "no_idc_source": {
        level: "warning",
        trigger: no_source_trigger("idc"),
        message: 'Should be after a Zotino or a HD68-IDC or with another IDC adapter.'
    },
    "clk_resource": {
        level: "warning",
        trigger: not_enough_resource_trigger("clk"),
        message: "Insufficient clock connectors."
    },
    "no_clk_source": {
        level: "warning",
        trigger: no_source_trigger("clk"),
        message: 'This card needs either a card that provides a clock source (e.g. Kasli or Clocker) at its left or use an external clock source.'
    },
    "eem_wiring_constraint": {
        level: "reminder",
        trigger: wiring_constraint("eem"),
        message: "Due to wiring constraints, the carrier can only connect to EEM cards immediately at its right, without crossing another carrier."
    },
    "default": {
        level: "warning",
        trigger: (_a, _b, _c) => {
            return true;
        },
        message: 'This item has unimplemented warning'
    }
}

export function TriggerWarnings(data, disabled) {
    return data.map((element, index) => {
        if (!element.warnings) return element;
        element.show_warnings = disabled ? [] :element.warnings
            .map((warning, _) => {
                if (!!Types[warning])
                    return Types[warning].trigger(data, index, element.counted_resources) ? {trigger: undefined, name: warning, ...Types[warning]} : null;
                else
                    return Types.default;
            })
            .filter((warning, _) => {
                return !!warning
            });
        return element;
    })
}

export function MaxLevel(warnings) {
    let mx = {priority: 0, icon: null};
    for (const warning of warnings) {
        if (Levels[warning.level].priority > mx.priority) mx = Levels[warning.level];
    }
    return mx;
}

export function LevelUI(warning_level) {
    const warning_t = Levels[warning_level];
    return {icon: warning_t.icon, color: warning_t.color};
}

const crate_warnings = {
    "overfit": {
        message: "You have reached the maximum number of slots allowed for this crate. Consider removing cards.",
        level: "warning",
        trigger: (crate, occupied) => {
            const nbrHP = useShopStore.getState().crateParams(crate.crate_mode).hp;
            return occupied > nbrHP && nbrHP > 0;
        }
    },
    "underfit_rack": {
        message: "The selected cards fit in a 42hp desktop crate, consider switching to it for a more compact system",
        level: "reminder",
        trigger: (crate, occupied) => {
            const nbrHPDesktop = useShopStore.getState().crate_modes.desktop.hp;
            return crate.crate_mode === useShopStore.getState().crate_modes.rack.id && occupied < nbrHPDesktop;
        }
    }
}

export function TriggerCrateWarnings(crate) {
    const nbrOccupied = resource_counters.hp(crate.items, -1);
    let warnings = [];
    Object.entries(crate_warnings).forEach(([id, warning], _) => {
        if (warning.trigger(crate, nbrOccupied)) warnings.push({...warning, id: id, trigger: undefined});
    })
    return [warnings, nbrOccupied];
}