var __extends = (this && this.__extends) || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
/// <reference path="ITemplateOptions.ts" />
/// <reference path="../net/Uri.ts" />
/// <reference path="../base/BaseClass.ts" />
/// <reference path="../util/DomHelper.ts" />
/// <reference path="../lib-definitions/ejs.d.ts" />
/// <reference path="../ajax/Ajax.ts" />
var econda;
(function (econda) {
    var templating;
    (function (templating) {
        var Uri = econda.net.Uri;
        var DomHelper = econda.util.DomHelper;
        /**
         * Wrapper for common template engines. Defaults to EJS template engine. Templates allow you
         * to render data to html using an html template. For details about the template syntax of ejs visit their website: <a href="http://embeddedjs.com/">http://embeddedjs.com/</a>
         *
         *
         * <h3>Example</h3>
         *
         *        // content of /path/to/template.html
         *        <div>Hello <%= firstName %> <%= lastName %></div>
         *
         *        // content of /page/where_we_use_the_template.html
         *
         *        var data = {
         *            firstName: "Edgar",
         *            lastName: "Gray"
         *        };
         *
         *        var myTemplate = new econda.templating.Template({
         *            uri: "/path/to/template.html"
         *        });
         *        var renderedHtml = myTemplate.render(data);
         *
         *        // set as content of a div element or - just as an example: show a message box
         *        alert(renderedHtml);
         *
         *
         *    <h4>Example Template</h4>
         *
         *	    <% columns = 5; i = 0; attributes = {'brand': '', 'arcticleno': 'Art.No.:'} %>
         *	    <div class="ec-widget">
         *	    <div class="ec-widget-products">
         *	    <div class="ec-widget-title">Recommendations</div>
         *	        <% for (act in products) { if (i == 0) { %>
         *	                <ul class="ec-widget-grid">
         *	           <% } %>
         *	                <li class="ec-widget-list">
         *	                    <div class="ec-widget-image"><a href="<%= products[act].deeplink %>" title="<%= products[act].name %>"><img src="<%= products[act].iconurl %>" alt="<%= products[act].name %>" /> </a></div>
         *	                    <div class="ec-widget-name"><a href="<%= products[act].deeplink %>" title="<%= products[act].name %>"><%= products[act].name %></a></div>
         *	                    <div class="ec-widget-price"><%= products[act].price %></div>
         *	                    <% for (attr in attributes) { if (products[act][attr]) { %>
         *	                    <div class="ec-widget-attribute"><%= attributes[attr] %>&nbsp;<%= products[act][attr] %></div>
         *	                    <% }} %>
         *	                </li>
         *	            <% i++; if (i == columns) {i= 0 %>
         *	            </ul>
         *	            <% }} %>
         *	    </div>
         *
         *
         * @class econda.templating.Template
         * @extends econda.base.BaseClass
         * @author Edgar Gaiser
         */
        var Template = (function (_super) {
            __extends(Template, _super);
            function Template(cfg) {
                _super.call(this);
                /**
                 * Instance reference of (ejs) template engine
                 * @private
                 */
                // _engineInstance: any = null;
                /**
                 * @cfg {econda.net.Uri} uri
                 * @accessor
                 * Uri from where we have to load the html template. Should be an absolute path (e.g. "/path/to/my_template.html").
                 */
                this.uri = null;
                /**
                 * Template source code if not loaded from server.
                 * @cfg {String} template
                 * @accessor
                 */
                this.template = null;
                /**
                 * @cfg {String} [engine="ejs"]
                 * @accessor
                 * Renderer engine to use. The only supported one is ejs. Please send us a feature request
                 * if you prefer another engine.
                 */
                this.engine = "ejs";
                /**
                 * @cfg {String} element
                 * @accessor
                 * HTML element or Id (or CSS path if jQuery is installed) to read the template source from. If the element contains an HTML comment tag, content of the first
                 * comment tag inside the referenced or given HTML element is used as template source.
                 *
                 *     <div id="mytemplate">
                 *       <!--
                 *           <div>This is my template</div>
                 *       -->
                 *     </div>
                 */
                this._element = null;
                if (cfg instanceof Template) {
                    return cfg;
                }
                this.initConfig(cfg, "uri");
            }
            Template.prototype.getUri = function () {
                return this.uri;
            };
            Template.prototype.setUri = function (uri) {
                this.uri = new Uri(uri);
                return this;
            };
            Template.prototype.getTemplate = function () {
                return this.template;
            };
            Template.prototype.setTemplate = function (source) {
                this.template = source;
                return this;
            };
            Template.prototype.getEngine = function () {
                return this.engine;
            };
            Template.prototype.setEngine = function (name) {
                name = name.toLowerCase();
                if (name != "ejs") {
                    throw "It's not possible to change the template engine in this version.";
                }
                return this;
            };
            Template.prototype.getElement = function () {
                return this._element;
            };
            Template.prototype.setElement = function (element) {
                this._element = element;
                return this;
            };
            /**
             * Render this template with given values
             * @param {Object} data
             * @param {Function} success
             * @param {Function} error
             */
            Template.prototype.render = function (data, success, error) {
                if (data === void 0) { data = null; }
                if (success === void 0) { success = null; }
                if (error === void 0) { error = null; }
                var templateUri = this.getUri(), template = this.getTemplate(), sourceElement = this.getElement();
                if (!templateUri && !template && !sourceElement) {
                    error("Cannot render template: No template or uri found.");
                    return;
                }
                // read from dom if needed
                if (!template && sourceElement) {
                    var templateSource = this._readTemplateSourceFromDom(sourceElement);
                    if (templateSource) {
                        template = templateSource;
                    }
                }
                if (!template && templateUri) {
                    // check cache
                    var templateFn = ejs.cache.get(templateUri.toString());
                    if (templateFn && success) {
                        success(templateFn(data));
                    }
                    else {
                        // load async
                        econda.ajax.Ajax.request({
                            uri: templateUri.toString(),
                            method: 'GET',
                            success: function (template) {
                                var templateFn = function (data) {
                                    var result;
                                    try {
                                        result = ejs.render(template, data, {
                                            escape: function (str) {
                                                return str;
                                            }
                                        });
                                        if (success) {
                                            success(result);
                                        }
                                    }
                                    catch (e) {
                                        if (error) {
                                            error(e);
                                        }
                                        else {
                                            console.warn(e);
                                        }
                                    }
                                    return result;
                                };
                                ejs.cache.set(templateUri.toString(), templateFn);
                                templateFn(data);
                            },
                            error: error ? function () {
                                error('error loading template');
                            } : null
                        });
                    }
                    // abort because we found cached data or we load it async
                    return;
                }
                // compile given html template
                if (template) {
                    var result;
                    try {
                        result = ejs.render(template, data, {
                            escape: function (str) {
                                return str;
                            }
                        });
                        if (success) {
                            success(result);
                        }
                    }
                    catch (e) {
                        if (error) {
                            error(e);
                        }
                        else {
                            console.warn(e);
                        }
                    }
                    return result;
                }
                error('error loading template');
                return;
            };
            Template.prototype._readTemplateSourceFromDom = function (element) {
                var e = DomHelper.element(element);
                var encodedTemplate = null;
                if (!e) {
                    return null;
                }
                encodedTemplate = e.innerHTML;
                for (var i = 0; i < e.childNodes.length; i++) {
                    if (e.childNodes[i].nodeType == 8) {
                        encodedTemplate = e.childNodes[i].textContent;
                        break;
                    }
                }
                // decode template tags
                return encodedTemplate.trim().replace('&lt;%', '<%').replace('%&gt;', '%>');
            };
            return Template;
        }(econda.base.BaseClass));
        templating.Template = Template; // end of class
    })(templating = econda.templating || (econda.templating = {}));
})(econda || (econda = {})); // end of module