import { ModifiableData } from "../actor/actor-data";

export type DS4ItemDataType =
    | DS4Weapon
    | DS4Armor
    | DS4Shield
    | DS4Spell
    | DS4Trinket
    | DS4Equipment
    | DS4Talent
    | DS4RacialAbility
    | DS4Language
    | DS4Alphabet;

// types

interface DS4Weapon extends DS4ItemBase, DS4ItemPhysical, DS4ItemEquipable {
    attackType: "melee" | "ranged" | "meleeRanged";
    weaponBonus: number;
    opponentDefense: number;
}

interface DS4Armor extends DS4ItemBase, DS4ItemPhysical, DS4ItemEquipable, DS4ItemProtective {
    armorMaterialType: "cloth" | "leather" | "chain" | "plate";
    armorType: "body" | "helmet" | "vambrace" | "greaves" | "vambraceGreaves";
}

export interface DS4Talent extends DS4ItemBase {
    rank: DS4TalentRank;
}

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

interface DS4Spell extends DS4ItemBase, DS4ItemEquipable {
    spellType: "spellcasting" | "targetedSpell";
    bonus: string;
    spellCategory:
        | "healing"
        | "fire"
        | "ice"
        | "light"
        | "darkness"
        | "mindAffecting"
        | "electricity"
        | "none"
        | "unset";
    maxDistance: UnitData<DistanceUnit>;
    effectRadius: UnitData<DistanceUnit>;
    duration: UnitData<TemporalUnit>;
    scrollPrice: number;
}

interface DS4Shield extends DS4ItemBase, DS4ItemPhysical, DS4ItemEquipable, DS4ItemProtective {}
interface DS4Trinket extends DS4ItemBase, DS4ItemPhysical, DS4ItemEquipable {}
interface DS4Equipment extends DS4ItemBase, DS4ItemPhysical {}
type DS4RacialAbility = DS4ItemBase;
type DS4Language = DS4ItemBase;
type DS4Alphabet = DS4ItemBase;

// templates

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

export function isDS4ItemDataTypePhysical(input: DS4ItemDataType): boolean {
    return "quantity" in input && "price" in input && "availability" in input && "storageLocation" in input;
}

interface DS4ItemEquipable {
    equipped: boolean;
}

interface DS4ItemProtective {
    armorValue: number;
}

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