/*
 * Copyright (c) 2017, Tony Opara
 *        All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions are met:
 * - Redistributions of source code must retain the above copyright notice, this 
 *   list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright notice, 
 *   this list of conditions and the following disclaimer in the documentation 
 *   and/or other materials provided with the distribution.
 * 
 * Neither the name of Google nor the names of its contributors may be used to 
 * endorse or promote products derived from this software without specific 
 * prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

//Internationalization init
var lang = navigator.language.split("-")[0]
    || navigator.userLanguage.split("-")[0];
var dictionary = "";
$.ajax({
  url : "command/core/load-language?",
  type : "POST",
  async : false,
  data : {
    module : "database",
  },
  success : function(data) {
    dictionary = data['dictionary'];
    lang = data['lang'];
  }
});
$.i18n().load(dictionary, lang);
// End internationalization

Refine.DatabaseImportController = function(createProjectUI) {
  this._createProjectUI = createProjectUI;
  
  this._parsingPanel = createProjectUI.addCustomPanel();

  createProjectUI.addSourceSelectionUI({
    label: "Database",
    id: "database-source",
    ui: new Refine.DatabaseSourceUI(this)
  });

};
Refine.CreateProjectUI.controllers.push(Refine.DatabaseImportController);

Refine.DatabaseImportController.prototype.startImportingDocument = function(queryInfo) {
    var dismiss = DialogSystem.showBusy($.i18n('database-import/preparing'));
    //alert(queryInfo.query);
    var self = this;
  
    Refine.postCSRF(
      "command/core/create-importing-job",
      null,
      function(data) {
        Refine.wrapCSRF(function(token) {
            $.post(
            "command/core/importing-controller?" + $.param({
                "controller": "database/database-import-controller",
                "subCommand": "initialize-parser-ui",
                "csrf_token": token
            }),
            queryInfo,
            
            function(data2) {
                dismiss();
                
                if (data2.status == 'ok') {
                self._queryInfo = queryInfo;
                self._jobID = data.jobID;
                self._options = data2.options;
                
                self._showParsingPanel();
                
                } else {
                alert(data2.message);
                }
            },
            "json"
            );
        });
      },
      "json"
    );
};

Refine.DatabaseImportController.prototype.getOptions = function() {
   var options = {
  
   };
  
    var parseIntDefault = function(s, def) {
      try {
        var n = parseInt(s);
        if (!isNaN(n)) {
          return n;
        }
      } catch (e) {
        // Ignore
      }
      return def;
    };

    
    if (this._parsingPanelElmts.skipCheckbox[0].checked) {
      options.skipDataLines = parseIntDefault(this._parsingPanelElmts.skipInput[0].value, 0);
    } else {
      options.skipDataLines = 0;
    }
    if (this._parsingPanelElmts.limitCheckbox[0].checked) {
      options.limit = parseIntDefault(this._parsingPanelElmts.limitInput[0].value, -1);
    } else {
      options.limit = -1;
    }
    options.storeBlankRows = this._parsingPanelElmts.storeBlankRowsCheckbox[0].checked;
    options.storeBlankCellsAsNulls = this._parsingPanelElmts.storeBlankCellsAsNullsCheckbox[0].checked;

    return options;
};

Refine.DatabaseImportController.prototype._showParsingPanel = function() {
    var self = this;
    
    this._parsingPanel.unbind().empty().html(
        DOM.loadHTML("database",'scripts/index/database-parsing-panel.html'));
        
    this._parsingPanelElmts = DOM.bind(this._parsingPanel);

    this._parsingPanelElmts.startOverButton.html($.i18n('database-parsing/start-over'));
    this._parsingPanelElmts.database_conf_pars.html($.i18n('database-parsing/conf-pars'));
    this._parsingPanelElmts.database_proj_name.html($.i18n('database-parsing/proj-name'));
    this._parsingPanelElmts.createProjectButton.html($.i18n('database-parsing/create-proj'));
    this._parsingPanelElmts.database_options.html($.i18n('database-parsing/option'));
    this._parsingPanelElmts.previewButton.html($.i18n('database-parsing/preview-button'));
    this._parsingPanelElmts.database_updating.html($.i18n('database-parsing/updating-preview'));
    this._parsingPanelElmts.database_discard_next.html($.i18n('database-parsing/discard-next'));
    this._parsingPanelElmts.database_discard.html($.i18n('database-parsing/discard'));
    this._parsingPanelElmts.database_limit_next.html($.i18n('database-parsing/limit-next'));
    this._parsingPanelElmts.database_limit.html($.i18n('database-parsing/limit'));
    this._parsingPanelElmts.database_store_row.html($.i18n('database-parsing/store-row'));
    this._parsingPanelElmts.database_store_cell.html($.i18n('database-parsing/store-cell'));
    
    if (this._parsingPanelResizer) {
      $(window).unbind('resize', this._parsingPanelResizer);
    }
    
    this._parsingPanelResizer = function() {
      var elmts = self._parsingPanelElmts;
      var width = self._parsingPanel.width();
      var height = self._parsingPanel.height();
      var headerHeight = elmts.wizardHeader.outerHeight(true);
      var controlPanelHeight = 250;

      elmts.dataPanel
      .css("left", "0px")
      .css("top", headerHeight + "px")
      .css("width", (width - DOM.getHPaddings(elmts.dataPanel)) + "px")
      .css("height", (height - headerHeight - controlPanelHeight - DOM.getVPaddings(elmts.dataPanel)) + "px");
      elmts.progressPanel
      .css("left", "0px")
      .css("top", headerHeight + "px")
      .css("width", (width - DOM.getHPaddings(elmts.progressPanel)) + "px")
      .css("height", (height - headerHeight - controlPanelHeight - DOM.getVPaddings(elmts.progressPanel)) + "px");

      elmts.controlPanel
      .css("left", "0px")
      .css("top", (height - controlPanelHeight) + "px")
      .css("width", (width - DOM.getHPaddings(elmts.controlPanel)) + "px")
      .css("height", (controlPanelHeight - DOM.getVPaddings(elmts.controlPanel)) + "px");
    };
    
    $(window).resize(this._parsingPanelResizer);
    this._parsingPanelResizer();
    
    this._parsingPanelElmts.startOverButton.click(function() {
      // explicitly cancel the import job
      Refine.CreateProjectUI.cancelImportingJob(self._jobID);
  
      delete self._jobID;
      delete self._options;
      
      self._createProjectUI.showSourceSelectionPanel();
    });
    
    this._parsingPanelElmts.createProjectButton.click(function() { self._createProject(); });
    this._parsingPanelElmts.previewButton.click(function() { self._updatePreview(); });
    //alert("datetime::" + $.now());
    //this._parsingPanelElmts.projectNameInput[0].value = this._queryInfo.connectionName + "_" + this._queryInfo.databaseUser + "_" + $.now();
    this._parsingPanelElmts.projectNameInput[0].value = this._queryInfo.databaseServer +  "_" + this._queryInfo.initialDatabase + "_" + $.now();

    
    if (this._options.limit > 0) {
      this._parsingPanelElmts.limitCheckbox.prop("checked", true);
      this._parsingPanelElmts.limitInput[0].value = this._options.limit.toString();
    }
    if (this._options.skipDataLines > 0) {
      this._parsingPanelElmts.skipCheckbox.prop("checked", true);
      this._parsingPanelElmts.skipInput.value[0].value = this._options.skipDataLines.toString();
    }
    if (this._options.storeBlankRows) {
      this._parsingPanelElmts.storeBlankRowsCheckbox.prop("checked", true);
    }
    if (this._options.storeBlankCellsAsNulls) {
      this._parsingPanelElmts.storeBlankCellsAsNullsCheckbox.prop("checked", true);
    }

    var onChange = function() {
      self._scheduleUpdatePreview();
    };
    this._parsingPanel.find("input").bind("change", onChange);
    this._parsingPanel.find("select").bind("change", onChange);
    
    this._createProjectUI.showCustomPanel(this._parsingPanel);
    this._updatePreview();
};

Refine.DatabaseImportController.prototype._scheduleUpdatePreview = function() {
    if (this._timerID != null) {
      window.clearTimeout(this._timerID);
      this._timerID = null;
    }

    var self = this;
    this._timerID = window.setTimeout(function() {
      self._timerID = null;
      self._updatePreview();
    }, 500); // 0.5 second
  };

Refine.DatabaseImportController.prototype._updatePreview = function() {
    var self = this;
   // alert("query::" + this._queryInfo.query);
    this._parsingPanelElmts.dataPanel.hide();
    this._parsingPanelElmts.progressPanel.show();
    this._queryInfo.options = JSON.stringify(this.getOptions());
    //alert("options:" + this._queryInfo.options);

    Refine.wrapCSRF(function(token) {
        $.post(
        "command/core/importing-controller?" + $.param({
            "controller": "database/database-import-controller",
            "jobID": self._jobID,
            "subCommand": "parse-preview",
            "csrf_token": token
        }),
        
        this._queryInfo,
        
        function(result) {
            if (result.status == "ok") {
                self._getPreviewData(function(projectData) {
                self._parsingPanelElmts.progressPanel.hide();
                self._parsingPanelElmts.dataPanel.show();

                new Refine.PreviewTable(projectData, self._parsingPanelElmts.dataPanel.unbind().empty());
            });
            } else {
            
            alert('Errors:\n' +  (result.message) ? result.message : Refine.CreateProjectUI.composeErrorMessage(job));
            self._parsingPanelElmts.progressPanel.hide();
            
            Refine.CreateProjectUI.cancelImportingJob(self._jobID);
            
            delete self._jobID;
            delete self._options;
            
            self._createProjectUI.showSourceSelectionPanel();
            
            
            }
        },
        "json"
        );
    });
  };

Refine.DatabaseImportController.prototype._getPreviewData = function(callback, numRows) {
    var self = this;
    var result = {};

    $.post(
      "command/core/get-models?" + $.param({ "importingJobID" : this._jobID }),
      null,
      function(data) {
        for (var n in data) {
          if (data.hasOwnProperty(n)) {
            result[n] = data[n];
          }
        }
        
        $.post(
          "command/core/get-rows?" + $.param({
            "importingJobID" : self._jobID,
            "start" : 0,
            "limit" : numRows || 100 // More than we parse for preview anyway
          }),
          null,
          function(data) {
            result.rowModel = data;
            callback(result);
          },
          "jsonp"
        );
      },
      "json"
    );
};

Refine.DatabaseImportController.prototype._createProject = function() {
    var projectName = $.trim(this._parsingPanelElmts.projectNameInput[0].value);
    if (projectName.length == 0) {
      window.alert("Please name the project.");
      this._parsingPanelElmts.projectNameInput.focus();
      return;
    }
    
    var self = this;
    var options = this.getOptions();
    options.projectName = projectName;
    
    this._queryInfo.options = JSON.stringify(options);
    Refine.wrapCSRF(function(token) {
        $.post(
        "command/core/importing-controller?" + $.param({
            "controller": "database/database-import-controller",
            "jobID": self._jobID,
            "subCommand": "create-project",
            "csrf_token": token
        }),
        this._queryInfo,
        function(o) {
            if (o.status == 'error') {
            alert(o.message);
            } else {
            var start = new Date();
            var timerID = window.setInterval(
                function() {
                self._createProjectUI.pollImportJob(
                    start,
                    self._jobID,
                    timerID,
                    function(job) {
                        return "projectID" in job.config;
                    },
                    function(jobID, job) {
                        //alert("jobID::" + jobID + " job :" + job);
                        window.clearInterval(timerID);
                        Refine.CreateProjectUI.cancelImportingJob(jobID);
                        document.location = "project?project=" + job.config.projectID;
                    },
                    function(job) {
                        alert(Refine.CreateProjectUI.composeErrorMessage(job));
                    }
                );
                },
                1000
            );
            self._createProjectUI.showImportProgressPanel($.i18n('database-import/creating'), function() {
                // stop the timed polling
                window.clearInterval(timerID);

                // explicitly cancel the import job
                Refine.CreateProjectUI.cancelImportingJob(jobID);

                self._createProjectUI.showSourceSelectionPanel();
            });
            }
        },
        "json"
        );
    });
};