import { ModifiableData } from "../common/common-data";
import { DS4 } from "../config";

export type ItemType = keyof typeof DS4.i18n.itemTypes;

export type DS4ItemData =
    | DS4WeaponData
    | DS4ArmorData
    | DS4ShieldData
    | DS4SpellData
    | DS4EquipmentData
    | DS4LootData
    | DS4TalentData
    | DS4RacialAbilityData
    | DS4LanguageData
    | DS4AlphabetData
    | DS4SpecialCreatureAbilityData;

export interface DS4ItemDataHelper<T, U extends ItemType> extends Item.Data<T> {
    type: U;
}

type DS4WeaponData = DS4ItemDataHelper<DS4WeaponDataData, "weapon">;
type DS4ArmorData = DS4ItemDataHelper<DS4ArmorDataData, "armor">;
type DS4ShieldData = DS4ItemDataHelper<DS4ShieldDataData, "shield">;
type DS4SpellData = DS4ItemDataHelper<DS4SpellDataData, "spell">;
type DS4EquipmentData = DS4ItemDataHelper<DS4EquipmentDataData, "equipment">;
type DS4LootData = DS4ItemDataHelper<DS4LootDataData, "loot">;
type DS4TalentData = DS4ItemDataHelper<DS4TalentDataData, "talent">;
type DS4RacialAbilityData = DS4ItemDataHelper<DS4RacialAbilityDataData, "racialAbility">;
type DS4LanguageData = DS4ItemDataHelper<DS4LanguageDataData, "language">;
type DS4AlphabetData = DS4ItemDataHelper<DS4AlphabetDataData, "alphabet">;
type DS4SpecialCreatureAbilityData = DS4ItemDataHelper<DS4SpecialCreatureAbilityDataData, "specialCreatureAbility">;

export type AttackType = keyof typeof DS4["i18n"]["attackTypes"];

export interface DS4WeaponDataData extends DS4ItemDataDataBase, DS4ItemDataDataPhysical, DS4ItemDataDataEquipable {
    attackType: AttackType;
    weaponBonus: number;
    opponentDefense: number;
}

export interface DS4ArmorDataData
    extends DS4ItemDataDataBase,
        DS4ItemDataDataPhysical,
        DS4ItemDataDataEquipable,
        DS4ItemDataDataProtective {
    armorMaterialType: "cloth" | "leather" | "chain" | "plate";
    armorType: "body" | "helmet" | "vambrace" | "greaves" | "vambraceGreaves";
}

export interface DS4TalentDataData extends DS4ItemDataDataBase {
    rank: DS4TalentRank;
}

export interface DS4TalentRank extends ModifiableData<number> {
    max: number;
}

export interface DS4SpellDataData extends DS4ItemDataDataBase, DS4ItemDataDataEquipable {
    spellType: "spellcasting" | "targetedSpellcasting";
    bonus: string;
    spellCategory:
        | "healing"
        | "fire"
        | "ice"
        | "light"
        | "darkness"
        | "mindAffecting"
        | "electricity"
        | "none"
        | "unset";
    maxDistance: UnitData<DistanceUnit>;
    effectRadius: UnitData<DistanceUnit>;
    duration: UnitData<TemporalUnit>;
    cooldownDuration: UnitData<TemporalUnit>;
    scrollPrice: number;
}

export interface DS4ShieldDataData
    extends DS4ItemDataDataBase,
        DS4ItemDataDataPhysical,
        DS4ItemDataDataEquipable,
        DS4ItemDataDataProtective {}

export interface DS4EquipmentDataData extends DS4ItemDataDataBase, DS4ItemDataDataPhysical, DS4ItemDataDataEquipable {}

export interface DS4LootDataData extends DS4ItemDataDataBase, DS4ItemDataDataPhysical {}

export type DS4RacialAbilityDataData = DS4ItemDataDataBase;

export type DS4LanguageDataData = DS4ItemDataDataBase;

export type DS4AlphabetDataData = DS4ItemDataDataBase;

export interface DS4SpecialCreatureAbilityDataData extends DS4ItemDataDataBase {
    experiencePoints: number;
}

// templates

interface DS4ItemDataDataBase {
    description: string;
}
interface DS4ItemDataDataPhysical {
    quantity: number;
    price: number;
    availability: "hamlet" | "village" | "city" | "elves" | "dwarves" | "nowhere" | "unset";
    storageLocation: string;
}

export function isDS4ItemDataTypePhysical(input: DS4ItemData["data"]): boolean {
    return "quantity" in input && "price" in input && "availability" in input && "storageLocation" in input;
}

interface DS4ItemDataDataEquipable {
    equipped: boolean;
}

interface DS4ItemDataDataProtective {
    armorValue: number;
}

interface UnitData<UnitType> {
    value: string;
    unit: UnitType;
}
type TemporalUnit = "rounds" | "minutes" | "hours" | "days" | "custom";
type DistanceUnit = "meter" | "kilometer" | "custom";