/// <reference path="StoredMemory.ts" />
/// <reference path="../../Elements/Classes/Say.ts" />
/// <reference path="../Modules/ContentHandler.ts" />
interface ContentTypeOptions {
    id : string;
    defaultValue : boolean;
    description : Say | string;
    currentValueDescription? : (c : ContentType) => Say | string;

    /**
     * Use sparingly. Content-Types that shouldn't be allowed to change are those that either:
     * - Fundamental to the game in some way. Most of these will only remain stuck until the game has enough content to make do without it.
     * - Something that's only a negative signal: signalizing that this content will not appear during development/gameplay at all, letting players know it isn't available and probably won't be.
     */
    changeable? : boolean;
}

class ContentType extends StoredMemory<boolean> {
    private description : Say;
    private valueDescription : (c : ContentType) => Say | string = () => { return new Say (JSON.stringify(this.getValue())); };
    private changeable : boolean = true;

    private static memoryPrefix = "ct_";

    public constructor (options : ContentTypeOptions) {
        super(ContentType.memoryPrefix + options.id, options.defaultValue);

        this.description = options.description instanceof Say ? options.description : new Say(options.description);

        this.valueDescription = options.currentValueDescription == undefined ? this.valueDescription : options.currentValueDescription;

        if (options.changeable == false) {
            this.storeValue(options.defaultValue); // prevent localStorage alterations from affecting something that can't be changed
            this.changeable = false;
        }

        ContentHandler.registerContentType(this);
    }

    public getDescription () {
        return this.description;
    }

    public getValueDescription () {
        let desc = this.valueDescription(this);
        if (desc instanceof Say) {
            return desc;
        } else {
            return new Say(desc);
        }
    }

    public toggle () {
        if (this.changeable) {
            this.storeValue(!this.getValue());
        }
    }

    public isAllowed() {
        return this.getValue();
    }

    public static MM = new ContentType({
        changeable : false, // There will be too little content at first for us to block part of it for no good reason, maybe at some point
        description : "Homosexual (M/M) sexual events",
        id : "MM",
        defaultValue : true
    });


    public static FF = new ContentType({
        changeable : false, // There will be too little content at first for us to block part of it for no good reason, maybe at some point
        description : "Homosexual (F/F) sexual events",
        id : "FF",
        defaultValue : true
    });


    public static MF = new ContentType({
        changeable : false, // There will be too little content at first for us to block part of it for no good reason, maybe at some point
        description : "Heterosexual (M/F) sexual events",
        id : "MF",
        defaultValue : true
    });


    public static Beast = new ContentType({
        changeable : true,
        description : "Sexual events with either monsters or magical beasts. MM/MF/FF take precedence over this one if blocked. Sufficiently human creatures do not get counted into this.",
        id : "Beast",
        defaultValue : true
    });


    public static Scat = new ContentType({
        changeable : false,
        description : "Scatologic sexual events",
        id : "Scat",
        defaultValue : false // There is no intention of ever adding these
    });

    public static Pee = new ContentType({
        changeable : false,
        description : "Sexual events with urine",
        id : "Urophilia",
        defaultValue : false // There is no intention of ever adding these
    });
}