/// <reference path="../Thing.ts" />
interface ClothingOptions extends ThingOptions {
    topDescription? : Say;
    bottomDescription? : Say;
    feetDescription? : Say;
}

interface ClothingWearerValue {
    weight : number;
    value : number;
}

class Clothing extends Thing {
    public slots : Array<number> = [];
    public transparentSlots : Array<number> = [];
    public layer : number = Clothing.LAYER_MEDIUM;
    public isVisible = false;
    public visibleOn : Array<number> = [];

    // Padding: gets added to current size. Can be negative
    // max: If current size > max, current size = max. On -1 this is not considered.
    // tight: If current size > tight, person becomes tight. On -1 this is not considered.
    // loose: if current size < loose, person becomes loose - can be overriden by covering clothes
    // If something is not used, leave as undefined
    // Would be fun to make them burst if too much over max, but that's not going to be used right now
    public breastPadding : number = 0;
    public maxBreastSize : number = -1;
    public tightBreastSize : number = -1;
    public looseBreastSize : number = 0;

    // Padding: gets added to current size. Can be negative
    // max: If current size > max, current size = max. On -1 this is not considered.
    // tight: If current size > tight, person becomes tight. On -1 this is not considered.
    // loose: if current size < loose, person becomes loose - can be overriden by covering clothes
    // If something is not used, leave as undefined
    // Would be fun to make them burst if too much over max, but that's not going to be used right now
    public crotchPadding : number = 0;
    public maxCrotchSize : number = -1;
    public tightCrotchSize : number = -1;
    public looseCrotchSize : number = 0;

    // Padding: gets added to current size. Can be negative
    // max: If current size > max, current size = max. On -1 this is not considered.
    // tight: If current size > tight, person becomes tight. On -1 this is not considered.
    // loose: if current size < loose, person becomes loose - can be overriden by covering clothes
    // If something is not used, leave as undefined
    // Would be fun to make them burst if too much over max, but that's not going to be used right now
    public buttPadding : number = 0;
    public maxButtSize : number = -1;
    public tightButtSize : number = -1;
    public looseButtSize : number = 0;

    /**
     * This function must be called any time anything could change clothing on a person.
     * Ripped a clothing? Update all clothes.
     * Changed breast size? Update all clothes.
     */
    public updateStatus () {
        this.visibleOn = [];
        this.visibleOn.push(...this.slots);
        let wearer = Thing.WearRelation.getLeft(this);
        if (wearer == undefined) return;

        let cloths = Thing.WearRelation.getRight(wearer);
        let coveredSlots = [];
        for (let i = 0; i < cloths.length; i++) {
            let worn = cloths[i];
            if ((worn != this) && worn.layer > this.layer) {
                coveredSlots.push(...worn.getCoveringSlots());
            }
        }

        this.visibleOn = this.visibleOn.filter(visible => {
            return coveredSlots.indexOf(visible) == -1;
        });

        this.isVisible = this.visibleOn.length > 0;
    }

    public getCoveringSlots () {
        if (this.transparentSlots.length == 0) {
            return this.slots.slice(0);
        }

        return this.slots.filter((value, index, array) => {
            return this.transparentSlots.indexOf(value) == -1;
        });
    }

    public static LAYER_LOWEST = 0;
    public static LAYER_LOW = 5;
    public static LAYER_MEDIUM = 10;
    public static LAYER_HIGH = 15;
    public static LAYER_HIGHEST = 20;

    public genderValue : number = 50;
    public sluttinessValue : number = 40;

    public getGenderWeight () {
        return this.visibleOn.length;
    }

    public getGenderValue () {
        return this.genderValue;
    }

    public getSluttinessWeight () {
        return this.visibleOn.length;
    }

    public getSluttinessValue () {
        return this.sluttinessValue;
    }

    public static getGenderValueOn (p : Thing) : ClothingWearerValue {
        let weight = 0;
        let value = 0;
        let clothes = Thing.WearRelation.getRight(p);
        for (let i = 0; i < clothes.length; i++) {
            weight += clothes[i].getGenderWeight();
            value += clothes[i].getGenderWeight() * clothes[i].getGenderValue();
        }
        return {
            weight : weight,
            value : value
        };
    }

    public static getSluttinessValueOn (p : Thing) : ClothingWearerValue {
        let weight = 0;
        let value = 0;
        let clothes = Thing.WearRelation.getRight(p);
        for (let i = 0; i < clothes.length; i++) {
            weight += clothes[i].getSluttinessWeight();
            value += clothes[i].getSluttinessWeight() * clothes[i].getSluttinessValue();
        }
        return {
            weight : weight,
            value : value
        };
    }
}
