/*
 * ADOBE CONFIDENTIAL
 *
 * Copyright (c) 2014 Adobe Systems Incorporated. All rights reserved.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of Adobe Systems Incorporated and its suppliers,
 * if any.  The intellectual and technical concepts contained
 * herein are proprietary to Adobe Systems Incorporated and its
 * suppliers and are protected by trade secret or copyright law.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from Adobe Systems Incorporated.
 */

/*jslint vars: true, node: true, plusplus: true, devel: true, nomen: true, indent: 4, node: true */
/*global csInterface: true*/
"use strict";

var $               = require("jquery"),
    _               = require("underscore"),
    Q               = require("q"),
    Path            = require("path"),
    Backbone        = require('backbone'),
    ServerInterface = require("./serverInterface.js"),
    Headlights      = require("./utils/Headlights"),
    FileDialog      = require("./fileDialog.js"),
    FileUtils       = require("./fileUtils.js"),
    Template        = require("./TemplateLoader"),
    Strings         = require("./LocStrings"),
    ActionRollup = require("./actionRollup.js"),
    JSXRunner       = require("./JSXRunner");

//for debug, comment in to clear the setting
//localPrefs.setPref("hasLayerNameWarningBeenDismissed", "");

var PanelView = Backbone.View.extend({
    
    $spinner: $(),
    $spinnerCursor: $(),
    
    events: {
        "click .extract-button": "extractAllAssets",
        "mousemove .spinner": "updateSpinnerCursor",
        "mouseleave .spinner": "hideCursorOnMouseLeave"
    },
    
    initialize: function (options) {
        
        var generatorModel = options.generatorModel || new Backbone.Model();
        generatorModel.defaultSettingsModel = generatorModel.defaultSettingsModel || new Backbone.Model();
        
        this.generatorModel = generatorModel;
        this.settings = generatorModel.defaultSettingsModel;
        
        this.listenTo(this.model, "change:exporting", this.renderSpinnerVisibility);
        this.listenTo(this.model, "change:exporting", this._updateExportingOnGeneratorModel);
        
        this.listenTo(this.generatorModel.layerCollection, "remove", this.persistUsersActions);
        this.listenTo(this.generatorModel.layerCollection, "change", this.persistUsersActions);
        
        this.generatorModel.delegateDocChangeHandler = this.driveDocumentChanging.bind(this);
        
        this._footerTemplate = _.template(Template.loadTemplate("../templates/footerView.html"));
        this._spinnerTemplate = _.template(Template.loadTemplate("../images/Cur_Spinner_11_11.svg"));
    },
    
    setExtractButtonEnablement: function () {
        this.stopListening(this.generatorModel.layerCollection, "remove", this.setExtractButtonEnablement);
        this.stopListening(this.generatorModel.layerCollection, "change", this.setExtractButtonEnablement);
        
        if (this.generatorModel.layerCollection.hasDisplayableItems()) {
            this.$extractBtn.prop("disabled", false);
            this.listenTo(this.generatorModel.layerCollection, "remove", this.setExtractButtonEnablement);
        } else {
            this.$extractBtn.prop("disabled", true);
            this.listenTo(this.generatorModel.layerCollection, "change", this.setExtractButtonEnablement);
        }
    },
    
    _updateExportingOnGeneratorModel: function () {
        this.generatorModel.set("exporting", this.model.get("exporting"));
    },
    
    _setActiveDocPS: function (docId, filePath) {
        var returnDeferred = Q.defer();
        _.defer(function () {
            JSXRunner.runJSX("setActiveDoc", docId, filePath, function (result) {
                returnDeferred.resolve(result);
            });
        });
        return returnDeferred.promise;
    },
    
    driveDocumentChanging: function (docChangeData) {
        var docChangeDeferred = Q.defer();
        
        if (this.changeDocsDialog && _.isFinite(docChangeData.lastDocID) && docChangeData.lastDocID !== docChangeData.newDocID) {
            this._setActiveDocPS(docChangeData.lastDocID, docChangeData.lastDocFilepath).then(function (result) {
                if (result === "success") {
                    this.persistUsersActions().then(function () {
                        this.logExportEvent(Headlights.SAVE_SWITCH_DOC);

                        ActionRollup.reset();
                        //set the active doc to the new doc
                        this._setActiveDocPS(docChangeData.newDocID, docChangeData.lastDocFilepath).then(function () {
                            docChangeDeferred.resolve(true);
                        });
                    }.bind(this));
                } else {
                    console.warn("PROBLEM: setActiveDoc returned " + result);
                    docChangeDeferred.resolve(false);
                    if (docChangeData.docClosed) {
                        Headlights.logEvent(Headlights.CREMA_ACTION, Headlights.FAILED_TO_REOPEN);
                    }
                }
            }.bind(this));
        } else {
            docChangeDeferred.resolve(true);
        }
        
        return docChangeDeferred.promise;
    },
    persistUsersActions: function () {
        Headlights.logEvent(Headlights.CREMA_FUNNEL, Headlights.SAVED);
        Headlights.logEvent(Headlights.CREMA_FUNNEL, Headlights.SAVED_WITH_CHANGES);
        return ActionRollup.apply().then(function (result) {
            ActionRollup.reset();
            return result;
        });
    },
    logExportEvent: function (headlightsEvent, exportedFiles) {
        if (this.generatorModel.layerCollection) {
            this.generatorModel.layerCollection.logExportedAssetData();
            // we're not making compCollection now, so don't bother logging it.
            // this.generatorModel.compCollection.logExportedAssetData();
        }
        Headlights.logEvent(Headlights.CREMA_ACTION, headlightsEvent);
        var manual = exportedFiles && exportedFiles.length > 0,
            auto = this.generatorModel.defaultSettingsModel.get("autoSaveOnUpdate");
        
        if (manual || auto) {
            Headlights.logEvent(Headlights.CREMA_FUNNEL, Headlights.EXPORT);
            if (manual && auto) {
                Headlights.logEvent(Headlights.CREMA_FUNNEL, Headlights.EXPORT_BOTH);
            } else if (manual) {
                Headlights.logEvent(Headlights.CREMA_FUNNEL, Headlights.EXPORT_MANUAL);
            } else {
                Headlights.logEvent(Headlights.CREMA_FUNNEL, Headlights.EXPORT_AUTO);
            }
        }
    },
    
    render: function () {
        this.renderFooter();
        this.cacheElements();
        this.renderSpinner();
        this.renderSubViews();
        this.setExtractButtonEnablement();
        this.$cancelBtn.addClass("hide");
        this.$saveBtn.addClass("hide");
        this.$extractBtn.removeClass("hide");
        return this;
    },
    
    cacheElements: function () {
        this.$cancelBtn = this.$(".cancel-button");
        this.$saveBtn = this.$(".save-button");
        this.$extractBtn = this.$(".extract-button");
    },
    
    renderSpinner: function () {
        var context = Template.createTemplateContext(Strings, {});
        this.$spinner = $("<div></div>").addClass("spinner spinner-cursor-area");
        this.$spinnerCursor = $("<div></div>").addClass("spinner-cursor").appendTo(this.$spinner);
        this.$spinnerCursor.html(this._spinnerTemplate(context));
        this.renderSpinnerVisibility();
        this.$el.append(this.$spinner);
    },
        
    renderSpinnerVisibility: function () {
        var show = this.model.get("exporting") || false;
        this.$spinner.toggleClass("hide", !show);
    },
    
    updateSpinnerCursor: function (e) {
        this.$spinnerCursor.show().offset({ top: e.clientY, left: e.clientX });
    },
    
    hideCursorOnMouseLeave: function () {
        this.$spinnerCursor.hide();
    },
    
    renderFooter: function () {
        var context;
        
        if (!this.$elFooter) {
            this.$elFooter = this.$("footer");
        }
        context = Template.createTemplateContext(Strings, {});
        this.$elFooter.html(this._footerTemplate(context));
    },
    
    renderSubViews: function () {
    },
    
    extractAllAssets: function () {
        Headlights.logEvent(Headlights.CREMA_ACTION, Headlights.CLICK_EXTRACT);
        var saveToPSD = false,
            docId = this.generatorModel.get("docId"),
            docFileBaseName = this.generatorModel.get("docFileBaseName"),
            docFileDirectory = this.generatorModel.get("docFileDirectory"),
            fileDialogDefaults = FileDialog.getExportDirectoryDefaults(docFileBaseName, docFileDirectory),
            canceled = function (err) {
                this.model.set("exporting", false);
                if (err !== "cancel") {
                    console.warn("Error in extractAllAssets: " + err.message);
                    csInterface.evalScript("app.bringToFront();");
                }
                return Q.reject(err);
            }.bind(this),
            exportFinished = function (result) {
                this.logExportEvent(Headlights.FINISH_EXTRACT, _.pluck(result, "value"));
                // also log special event to match what generator uses when it renders crema-related assets automatically
                // (but it specifically doesn't do headlights logging when we call it explicitly;
                // that is turned off in generator-assets-patches/main.js)
                Headlights.logEvent(Headlights.GENERATOR, Headlights.GEN_RENDERED_CREMA);
                Headlights.logEvent(Headlights.CREMA_ACTION, saveToPSD ? Headlights.SAVE_EXPORT : Headlights.NO_SAVE_EXPORT);
                return ServerInterface.sendCommand("stopExtractingForThisConnection", {docId: docId});
            }.bind(this),
            exportToDirectory = function (directory) {
                this.model.set("exporting", true);
                //hack for windows crash, if we are going to auto-generate into the same folder then don't do the export
                if (fileDialogDefaults.isWin && this.generatorModel.defaultSettingsModel.get("autoSaveOnUpdate") &&
                        Path.normalize(directory) === Path.normalize(fileDialogDefaults.path)) {
                    FileUtils.openFolderInOS(fileDialogDefaults.isWin, directory);
                    return exportFinished();
                } else {
                    return ActionRollup.enableTempDefaultLayer().then(function () {
                        return ServerInterface.sendCommand("exportAllToFolder", {docId: docId, destFolder: directory}).then(exportFinished, canceled);
                    }, canceled);
                }
            }.bind(this),
            commitSave = function () {
                if (saveToPSD) {
                    return this.persistUsersActions();
                } else {
                    return Q.resolve();
                }
            }.bind(this),
            close = function () {
                this.model.set("exporting", false);
            }.bind(this);
        return FileDialog.promptForExportDirectory(docFileBaseName, docFileDirectory)
            .then(exportToDirectory, canceled)
            .then(commitSave, canceled)
            .then(close, canceled);
    }

});

module.exports = PanelView;
