﻿namespace MarionetteExt
{
    export interface ItemViewExtOptions<TModel extends Backbone.Model> extends Backbone.Marionette.ItemViewOptions<TModel>
    {
        parentEl?: any;
        destroyParent?: boolean;
    }

    // This is an extension of the Marionette ItemView class (inherits from ItemView).
    // We define a new option parentEl that the user supplies.
    // By default, the parentEl is not removed from the DOM when the view is destroyed
    // which Marionette normally does, unless you specify the destroyParent option.
    export class ItemViewExt<TModel extends Backbone.Model> extends Backbone.Marionette.ItemView<TModel>
    {
        private _parentEl: any = undefined;
        private _destroyParent: boolean = false;

        constructor(options: ItemViewExtOptions<TModel>)
        {
            super(ItemViewExt.ReconfigureOptions(options));

            // Check the options provided

            if (options.parentEl !== undefined)
            {
                this._parentEl = options.parentEl;
            }

            if (options.destroyParent)
            {
                this._destroyParent = options.destroyParent;
            }

            // Check that parentEl has been defined
            // You can define it in the constructor or
            // in the subclass definition
            if (this._parentEl === undefined)
            {
                throw "ItemViewExtError requires parentEl property";
            }

        }

        private static ReconfigureOptions(options: any): any
        {
            // Rename the "el" option to "parentEl".
            // You can now use "el" and "tagName" properties
            // together if you wish.
            if (options.el !== undefined)
            {
                options.parentEl = options.el;
                options.el = undefined;
            }
            return options;
        }

        // Override
        onRender(): void
        {
            $(this._parentEl).append(this.el);
        }

        // Override
        onDestroy(): void
        {
            if (this._destroyParent == true)
            {
                $(this._parentEl).remove();
            }
        }
    }

    export interface CollectionViewExtOptions<TModel extends Backbone.Model, TView extends Backbone.Marionette.View<Backbone.Model>> extends Backbone.Marionette.CollectionViewOptions<TModel, TView>
    {
        parentEl?: any;
        destroyParent?: boolean;
    }

    // This is an extension of the Marionette CollectionView class (inherits from CollectionView).
    // We define a new option parentEl that the user supplies.
    // By default, the parentEl is not removed from the DOM when the view is destroyed
    // which Marionette normally does, unless you specify the destroyParent option.
    export class CollectionViewExt<TModel extends Backbone.Model, TView extends Backbone.Marionette.View<Backbone.Model>> extends Backbone.Marionette.CollectionView<TModel, TView>
    {
        private _parentEl: any = undefined;
        private _destroyParent: boolean = false;

        constructor(options: CollectionViewExtOptions<TModel, TView>)
        {
            super(CollectionViewExt.ReconfigureOptions(options));

            // Check the options provided

            if (options.parentEl !== undefined)
            {
                this._parentEl = options.parentEl;
            }

            if (options.destroyParent)
            {
                this._destroyParent = options.destroyParent;
            }

            // Check that parentEl has been defined
            // You can define it in the constructor or
            // in the subclass definition
            if (this._parentEl === undefined)
            {
                throw "CollectionViewExtError requires parentEl property";
            }
        }

        private static ReconfigureOptions(options: any): any
        {
            // Rename the "el" option to "parentEl".
            // You can now use "el" and "tagName" properties
            // together if you wish.
            if (options.el !== undefined)
            {
                options.parentEl = options.el;
                options.el = undefined;
            }
            return options;
        }

        // Override
        onRender(): void
        {
            $(this._parentEl).append(this.el);
        }

        // Override
        onDestroy(): void
        {
            if (this._destroyParent == true)
            {
                $(this._parentEl).remove();
            }
        }
    }

    export interface LayoutViewExtOptions<TModel extends Backbone.Model> extends Backbone.Marionette.LayoutViewOptions<TModel>
    {
        parentEl?: any;
        destroyParent?: boolean;
    }

    // This is an extension of the Marionette LayoutView class (inherits from LayoutView).
    // We define a new option parentEl that the user supplies.
    // By default, the parentEl is not removed from the DOM when the view is destroyed
    // which Marionette normally does, unless you specify the destroyParent option.
    export class LayoutViewExt<TModel extends Backbone.Model> extends Backbone.Marionette.LayoutView<TModel>
    {
        private _parentEl: any = undefined;
        private _destroyParent: boolean = false;

        constructor(options: LayoutViewExtOptions<TModel>)
        {
            super(LayoutViewExt.ReconfigureOptions(options));

            // Check the options provided

            if (options.parentEl !== undefined)
            {
                this._parentEl = options.parentEl;
            }

            if (options.destroyParent)
            {
                this._destroyParent = options.destroyParent;
            }

            // Check that parentEl has been defined
            // You can define it in the constructor or
            // in the subclass definition
            if (this._parentEl === undefined)
            {
                throw "LayoutViewExtError requires parentEl property";
            }

        }

        private static ReconfigureOptions(options: any): any
        {
            // Rename the "el" option to "parentEl".
            // You can now use "el" and "tagName" properties
            // together if you wish.
            if (options.el !== undefined)
            {
                options.parentEl = options.el;
                options.el = undefined;
            }
            return options;
        }

        // Override
        onRender(): void
        {
            $(this._parentEl).append(this.el);
        }

        // Override
        onDestroy(): void
        {
            if (this._destroyParent == true)
            {
                $(this._parentEl).remove();
            }
        }

        // Override
        removeRegions(): void
        {
            this.regions = <any>{};
            this.getRegionManager().removeRegions();
        }
    }
}
