﻿namespace MarionetteExt
{
    export class AttributeHash
    {
        private _attributes: any = {};
        private _internalAttrs: string[] = [];

        public constructor(attributes: any, internal: any)
        {
            this.BuildAttributes(attributes, internal);
        }

        get Attributes(): any { return this._attributes; }
        get FilterList(): string[] { return this._internalAttrs; }

        private BuildAttributes(attributes: any, internal: any): void
        {
            let self: AttributeHash = this;
            this._attributes = _.clone(attributes);
            Object.keys(internal).forEach(function (key)
            {
                self._internalAttrs.push(key);
                self._attributes[key] = internal[key];
            });
        }

        //private CheckAttributes(attributes: any): void
        //{
        //    Object.keys(attributes).forEach(function (key)
        //    {
        //        let value: any = attributes[key];
        //        let parts: string[] = key.split(":", 2);

        //        if (parts.length == 2 && parts[1] == 'internal')
        //        {
        //            this._internalAttrs.push(parts[0]);
        //            key = parts[0];
        //        }
        //        attributes[key] = value;
        //    });
        //}
    }


    // Allows you to define a Model with two types of attributes, those that
    // should be saved to the webservice and those that are just kept
    // local to the application. This allows you to add extra attributes
    // for displaying on the View. using the template in the normal way.
    // Example:
    // let o: MyModelExt = new MyModelExt(new AttributeHash({
    //    attr1: string     // model attribute (as normal)
    // },
    // {
    //    attr2: string     // internal attribute just for View
    // }));
    export class ModelExt extends Backbone.Model
    {
        private _filtered: string[] = [];

        constructor(attributes?: AttributeHash|Object, options?: any)
        {
            super(ModelExt.LoadAttributes(attributes), options);
            if (attributes !== undefined)
            {
                if (attributes instanceof AttributeHash)
                {
                    this._filtered = attributes.FilterList;
                }
            }
        }

        private static LoadAttributes(attributes?: any): any
        {
            if (attributes !== undefined)
            {
                if (attributes instanceof AttributeHash)
                {
                    let hash: AttributeHash = <AttributeHash>attributes;    
                    return hash.Attributes;
                }
            }
            return attributes;
        }

        SetFilter(attrName: string, filter: boolean): boolean
        {
            if (filter == false)
            {
                let index: number = this._filtered.indexOf(attrName);
                if (index > -1)
                {
                    this._filtered = this._filtered.splice(index, 1);
                    return true;
                }
            }
            else
            {
                this._filtered.push(attrName);
                return true;
            }
            return false;
        }

        // Override the save () method
        save(attributes?: any, options?: Backbone.ModelSaveOptions): any
        {
            options = options || {};
            attributes = _.extend({}, _.clone(this.attributes), attributes);

            // Filter the data to send to the server
            attributes = _.omit(attributes, this._filtered);
            options.attrs = attributes;

            // Proxy the call to the original save function
            return super.save(attributes, options);
        }
    }
}