﻿enum ModelUrlType { Create = 0, Read = 1, Update = 2, Delete = 3 };
enum ModelStatus { Created, Read, Updated, Deleted, Dropped, AjaxError };

abstract class Model
{
    // Attributes
    private _data: Object;
    private _primaryKeyName: string = "id";
    private _primaryKeySet: boolean = false;
    private _urls: string[] = [];

    private static _ajaxSetup: boolean = true;

    // Constructor
    constructor(dataFields: any, primaryKeyName: string, urls: string[])
    {
        this._data = dataFields;
        this._primaryKeyName = primaryKeyName;
        this._urls = urls;
        Model.AjaxSetup();
    }


    // Properties
    get PrimaryKeyName(): string
    {
        return this._primaryKeyName;
    }

    get PrimaryKey(): number
    {
        return this.GetData(this._primaryKeyName);
    }

    set PrimaryKey(value: number)
    {
        this.SetData(this._primaryKeyName, value);
    }

    protected get PrimaryKeyNameValue(): Object
    {
        var priKey = {};
        priKey[this.PrimaryKeyName] = this.PrimaryKey;
        return priKey;
    }

    // Methods
    static AjaxSetup(): void
    {
        if (this._ajaxSetup)
        {
            $.ajaxSetup({ cache: false });  // May need to turn off browser page cache
            this._ajaxSetup = false;
        }
    }

    protected GetData(propName: string): any
    {
        if (this._data[propName] !== undefined) // Does field exist?
        {
            // If reading the primary key value and it hasn't been set, then return undefined.
            return (this._primaryKeySet || propName != this._primaryKeyName) ? this._data[propName] : undefined;
        }
        return undefined;
    }

    protected SetData(propName: string, value: any): boolean
    {
        if (this._data[propName] !== undefined || propName == this._primaryKeyName)
        {
            if (value !== undefined)
            {
                this._data[propName] = value;
                if (!this._primaryKeySet && propName == this._primaryKeyName) this._primaryKeySet = true;   // Note the primary key has been provided
                return true;
            }
        }
        return false;
    }

    protected Url(urlType: ModelUrlType, args?: Object): string
    {
        if (this._urls[urlType] !== undefined)
        {
            return this.UrlAppendPostfix(this._urls[urlType], args);
        }
        else
        {
            throw new Error("No postfix supplied for url type " + urlType);
        }
    }

    protected UrlAppendPostfix(postfix: string, args?: Object): string
    {
        var url: IUrl = Url.Create();
        url.Append(postfix);
        if (args)
        {
            url.AppendArgs(args);
        }
        return url.Url;
    }

    ToHTMLPairs(skipList?: string[]): string
    {
        return HTMLPairsConvertor.ConvertObjToPairs(this._data, skipList);
    }

    abstract Create(): boolean;
    abstract Read(): boolean;
    abstract Update(): boolean;
    abstract Delete(): boolean;
} 