///<reference path="../ContentMolecule.ts"/>
class ContentMoleculeFucking extends ContentMolecule {
    protected say : Say | ((relevantAtoms : Array<ContentAtomFucking>) => Say);
    protected saidTimes = 0;

    public constructor (description : Say | ((relevantAtoms : Array<ContentAtomFucking>) => Say)) {
        super();
        this.say = description;
        ContentMoleculeFucking.MOLECULES.push(this);
    }

    public getSay(specificMolecule : ContentMolecule, relevantAtoms : Array<ContentAtomFucking>) {
        this.saidTimes++;
        if (this.say instanceof Say) {
            return this.say;
        } else {
            //let relevantAtoms = specificMolecule.findMatches([this.fuckingAtom])
            //let fuckingAtom = <ContentAtomFucking>(specificMolecule.getAtoms()[0]);
            return this.say(relevantAtoms);
        }
    }

    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 : Array<ContentMoleculeFucking>  = [];

    /**
     * Searches for Fucking molecules that describe the specificMolecule given. Assumes atoms are of the Fucking variety.
     * @param specificMolecule
     */
    public static getSay (specificMolecule : ContentMolecule) {
        // Randomize the array to prevent the same message from showing up every time
        let many : Array<ContentMoleculeFucking> = new Shuffler(ContentMoleculeFucking.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 say = new Say("Unable to find match for this sexual passage.");
            specificMolecule.getAtoms().forEach((atom : ContentAtomFucking) => {
                say.add(Say.LINE_BREAK, "Fucker: ", atom.fucker,
                    ". Fucked: ", atom.fucked,
                    ". Stick: ", atom.stick,
                    ". Hole: ", atom.hole,
                    ". Markers: ", ...(atom.markers.getNouns()),
                    ". Please report for fixing."
                );
            });
            Elements.CurrentTurnHandler.printAsError(say);
            return new Say();
        } else {
            let finalSay = new Say();
            matches.forEach((idx : number) => {
                let value = ContentMoleculeFucking.MOLECULES[idx];
                finalSay.add(
                    value.getSay(
                        specificMolecule, specificMolecule.findMatches([value], true)
                    )
                );
                finalSay.add(" ");
            });
            return finalSay;
        }
    }
}