///<reference path="../ContentMolecule.ts"/>
class ContentMoleculeAnnoy extends ContentMolecule {
    protected say : Say | ((attacker : any, target : any, markers : Array<ContentNounSimple>) => Say);
    protected saidTimes = 0;

    public constructor (description : Say | ((attacker : any, target : any, markers : Array<ContentNounSimple>) => Say)) {
        super();
        this.say = description;
        ContentMoleculeAnnoy.MOLECULES.push(this);
    }

    public getSay(specificMolecule : ContentMolecule) {
        this.saidTimes++;
        if (this.say instanceof Say) {
            return this.say;
        } else {
            let combatAtom = <ContentAtomAnnoy>(specificMolecule.getAtoms()[0]);
            return this.say(combatAtom.annoyer, combatAtom.target, combatAtom.markers.getNouns());
        }
    }

    public getWeight () {
        // TODO: Check if this implementation is good enough.
        let weight = -this.saidTimes;
        this.atoms.forEach(value => {
            weight += value.getAtomPriority()
        });
        return weight;
    }

    protected static MOLECULES = [];

    /**
     * Searches for Combat molecules that describe the specificMolecule given. Assumes Atoms are of the Combat variety. Assumes there is always a single Atom.
     * @param specificMolecule
     */
    public static getSay (specificMolecule : ContentMolecule) {
        // Randomize the array to prevent the same message from showing up every time
        let many : Array<ContentMoleculeAnnoy> = new Shuffler(ContentMoleculeAnnoy.MOLECULES).getShuffled();

        // Order the array placing higher priority messages on top, but messages with same priority are still randomized
        many.sort((a, b) => {
            return b.getWeight() - a.getWeight()
        });

        let matches = specificMolecule.findMatches(many);
        if (matches.length == 0) {
            let atom = <ContentAtomAnnoy> specificMolecule.getAtoms()[0];
            Elements.CurrentTurnHandler.printAsError(
                new Say(
                    "Unable to find match for this annoying passage. Attacker: ", atom.annoyer,
                    ". Target: ", atom.target,
                    ". Markers: ", ...(atom.markers.getNouns()),
                    ". Please report for fixing."
                )
            );
            return new Say();
        } else {
            let finalSay = new Say();
            matches.forEach((idx : number) => {
                finalSay.add(ContentMoleculeAnnoy.MOLECULES[idx].getSay(specificMolecule));
                finalSay.add(" ");
            });
            return finalSay;
        }
    }
}