/*
 * ADOBE CONFIDENTIAL
 *
 * Copyright (c) 2013-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, plusplus: true, devel: true, nomen: true, indent: 4, regexp: true */
/*global define: true, graphite: true, window: true*/

define([
    'jquery',
    'underscore',
    'backbone',
    'plugin-dependencies',
    'ccweb.files.extract/controllers/DerivedAssetController',
    'ccweb.files.extract/controllers/SelectionController',
    'ccweb.files.extract/views/popup/BasePopupView',
    'ccweb.files.extract/utils/TemplateUtil',
    'ccweb.files.extract/utils/LayerNameParser',
    'ccweb.files.extract/utils/SpriteSheetUtils',
    'DWPSDExtractManager',
    'parfait/ExtractAssetView',
    'dreamweaver/controllers/PreferenceController',
    'ccweb.files.extract/models/UserSettingsModel',
    'ccweb.files.extract/Constants',
    'text!ccweb.files.extract/views/templates/extractAssetTemplate.html'
], function ($, _, Backbone, deps, DerivedAssetController, SelectionController,
    BasePopupView, TemplateUtil, LayerNameParser, SpriteSheetUtils, DWPSDExtractManager, ExtractAssetView, PreferenceController, UserSettingsModel, Constants, ExtractAssetTemplate) {
    "use strict";
    
    var DEFAULT_JPEG_QUALITY = 80;
    // If you need to change the forbidden characters, change both this and
    // `REPLACE_RE`.
    var FORBIDDEN_CHARACTERS = '/\\\\:*?"<>|,';
    var FORBIDDEN_CHARACTERS_PLUS_WHITESPCE = FORBIDDEN_CHARACTERS + '\\s';
    // Used for the `pattern` attribute of the name input. Whitespace rules
    // ensure no no names that consist of *just* whitespace
    var VALIDATION_PATTERN = '^[^' + FORBIDDEN_CHARACTERS + ']*' +
        '[^' + FORBIDDEN_CHARACTERS_PLUS_WHITESPCE + '][^' + FORBIDDEN_CHARACTERS + ']*$';
    // Although it would be nice to generate this from FORBIDDEN_CHARACTERS,
    // several characters like `*` need extra escaping, making it a bit too
    // much of a pain
    var REPLACE_RE = /(\/|\\|:|\*|\?|"|<|>|\||\,|^\.\.\.)/g;

    var DwExtractAssetView = ExtractAssetView.extend({
        $qualityRange: null,
        $qualityPercent: null,
        defaultExtension: 'png',
        defaultPreferredImageQuality: 80,
        folderNameInputClass: 'folder-name-input',
        imageDownloadPath: '',
        imageDownloadUrl: '',
        fileNameInputClass: 'file-name-input',
        downloadButtonId: 'downloadBtn',
        batchDownloadButtonId: 'batchDownloadBtn',
        batchDwnldSettingsBtnId: 'batchDwnldSettingsBtn',
        batchDwnldBtnsGroupId: 'batchDownloadGroup',
        description: {
            png8: deps.translate("PNG8_DESCRIPTION"),
            png32: deps.translate("PNG32_DESCRIPTION"),
            svg: deps.translate("SVG_DESCRIPTION")
        },

        responseCodes: [
            "ErrorType_UNKNOWN",
            "ErrorType_PATHEMPTY",
            "ErrorType_FILENAME_EMPTY",
            "ErrorType_FILEEXISTS",
            "ErrorType_RELATIVEURL_FOR_DOWNLOAD",
            "ErrorType_INVALIDFILEPATH",
            "ErrorType_DIRECTORY_CREATION_FAILED",
            "ErrorType_INVALID_URL",
            "Response_Valid"
        ],
        
        responseErrorStrings: [
            "UNKNOWN_ERROR",
            "ENTER_A_FOLDER",
            "ENTER_A_FILE_NAME",
            "FILENAME_ALREADY_EXISTS",
            "PLEASE_ENTER_ABSOLUTE_PATH",
            "INVALID_PATH",
            "CANNOT_CREATE_DIRECTORY_STRUCTURE",
            "INVALID_PATH"
        ],
        
        events: function () {
            return _.extend({}, ExtractAssetView.prototype.events, {
                "click #folder-browse-button": "handleFolderBrowse",
                "focus .folder-name-input": "removeErrorHighlight",
                "focus .file-name-input": "removeErrorHighlight",
                "focus .options input[type=radio]": "addFocusHighlight",
                "focus div.scale input[type='checkbox']": "addFocusHighlight",
                "blur .options input[type=radio]": "removeFocusHighlight",
                "blur div.scale input[type='checkbox']": "removeFocusHighlight",
                "keydown .folder-name-input": "handleKeydownOnPathInputs",
                "keydown .file-name-input": "handleKeydownOnPathInputs",
                "keydown #downloadBtn": "handleTabOrdering",
                "keyup #folder-browse-button": "handleBrowseButtonKeydown",
                "keyup .scale-enable": "handleKeydownOnScaleEnable",
                "click #batchDwnldSettingsBtn": "showBatchExportSettings",
                "click #batchDownloadBtn": "handleBatchExportAsset"
            });
        },
        
        initialize: function () {
            PreferenceController.on("change:Preferences", this.handlePreferenceUpdate, this);
            DWPSDExtractManager.getExtractPreferences();
            this.defaultExtension = PreferenceController.get("preferredFileExtension");
            this.defaultPreferredImageQuality = PreferenceController.get("preferredImageQuality");
            ExtractAssetView.prototype.initialize.apply(this, arguments);
        },
        
        handleExportAssetError: function (result) {
            if (result.status === 401) {
                graphite.events.trigger('reauthenticate');
            } else if (result.status === 507) {
                deps.notifyUser(deps.translate("Error extracting asset. You've possibly exceeded your storage limit."));
            } else {
                graphite.events.trigger("load-alert", deps.translate("ERROR_RETRIEVING_DERIVED_ASSETS"));
            }
        },
        
        /**
         * Leverages the generator parser to infer extracted asset details
         * such as file name, encoding, optimization, etc. As we move forward,
         * Extract will be able to honor more and more of these hints.
         */
        deriveAssetDetailsFromLayer: function (layerModel) {
            var fileName = layerModel.get('layerName'),
                format = 'png32',
                extractInfo,
                assetDetails,
                quality,
                scale,
                extension;

            // Remove leading chars
            fileName = fileName.replace(/^(\/|\\|\.)+/, '');

            var jpegQuality = DEFAULT_JPEG_QUALITY;

            try {
                extractInfo = LayerNameParser.parse(fileName);
                if (extractInfo && extractInfo.length > 0) {
                    assetDetails = extractInfo[0];
                    fileName = assetDetails.file || fileName;
                    quality = assetDetails.quality;
                    scale = assetDetails.scale;
                    extension = assetDetails.extension || this.defaultExtension || "png";

                    switch (extension.toLowerCase()) {
                    case "jpg":
                    case "jpeg":
                    case "gif":
                        format = "jpg";
                        jpegQuality = this.defaultPreferredImageQuality || 80;
                        break;
                    case 'png32':
                        format = 'png32';
                        break;
                    case 'png8':
                        format = 'png8';
                        break;
                    }
                }
            } catch (e) {}

            this.updatePercent(jpegQuality);
            this.updateRange(jpegQuality);

            if (scale && scale !== 1 && scale >= 0.1 && scale <= 5) {
                this.$scaleEnabled.prop('checked', true);
                this.$scale.toggleClass('disabled', false);
                this.$scaleFactor.val(parseFloat(scale.toFixed(1)) + 'x');
            }

            this.setFileFormat(format);
            if (assetDetails && assetDetails.extension && (assetDetails.extension === "jpg" || assetDetails.extension === "jpeg" || assetDetails.extension === "png")) {
                fileName = fileName.substr(0, fileName.lastIndexOf('.')) || fileName;
            }
            fileName = this.normalizeFileName(fileName);
            fileName = fileName.replace(/\s+/g, "_");
            if (deps.utils.hasFeature('extract_batch')) {
                this.baseName = fileName;
            } else {
                this.$fileName.val(fileName);
            }
        },
        
        addFocusHighlight: function (e) {
            // For some reason the border doesn't appear on the focused radio element.
            // So in these cases, we highlight the parent instead.
            // Also since radio buttons appear touching each other we have to add an extra border
            // on the right for all radio buttons but the last one
            var focusClass = "focus-highlight",
                radioButtonContainers,
                elementIndex = 0;
            if (e.target.type === "radio") {
                radioButtonContainers = Array.prototype.slice.call(this.$el.find(".image-type-parent"), 0);
                radioButtonContainers.forEach(function (radioButtonParent, index) {
                    if (radioButtonParent === $(e.target).parent()[0]) {
                        elementIndex = index;
                    }
                });
                if (elementIndex < radioButtonContainers.length - 1) {
                    focusClass = "focus-highlight-border";
                }
            }
            
            $(e.target).parent().addClass(focusClass);
        },
        
        handleKeydownOnScaleEnable: function (e) {
            // On Mac checkboxes are not toggling on space, we have to handle this 
            if (e.keyCode === 32 && window.dwData.OsType === "MAC") {
                this.$scaleEnabled.prop("checked", !this.$scaleEnabled.prop("checked"));
                this.$scaleEnabledChanged();
            }
        },
        
        removeFocusHighlight: function (e) {
            // Clear any existing highlight
            $(e.target).parent().removeClass("focus-highlight");
            $(e.target).parent().removeClass("focus-highlight-border");
        },
        
        handleBrowseButtonKeydown: function (e) {
            if (e.keyCode === 13 || e.keyCode === 32) {
                this.handleFolderBrowse();
            }
        },
        
        scaleEnabledChanged: function () {
            ExtractAssetView.prototype.scaleEnabledChanged.apply(this, arguments);
            if (this.$scaleEnabled.prop("checked")) {
                this.$scaleFactor.attr("tabindex", "10");
                 // "Scale at" setting is not applicable to batch download, so disable it.
                this.$batchDownloadButton.attr('disabled', '');
                this.$batchDownloadButton.attr("tabindex", "-1");
            } else {
                this.$scaleFactor.attr("tabindex", "-1");
                this.$batchDownloadButton.removeAttr('disabled');
                this.$batchDownloadButton.attr("tabindex", "12");
            }
        },
        
        render: function () {
            BasePopupView.prototype.render.apply(this, arguments);

            this.$el.find('.popup-contents').html(TemplateUtil.createTemplate(ExtractAssetTemplate, {settings: UserSettingsModel, fileExtension: "." + this.getDefaultFileextension()}));
            
            this.$fileName = this.$el.find('.file-name-input');
            this.$qualityRange = this.$el.find('.quality-range');
            this.$qualityPercent = this.$el.find('.quality-percentage');
            this.$fileFormat = this.$el.find('.options');
            this.$sizeSpan = this.$el.find('#extract-size-value');
            this.$extractSize = this.$el.find('.extract-size');
            this.$qualityLabel = this.$el.find('.subtitle');
            this.$qualityBox = this.$el.find('.quality');
            this.$formatDescription = this.$el.find('.format-description');
            this.$scale = this.$el.find('.scale');
            this.$scaleEnabled = this.$el.find('.scale-enable');
            this.$scaleFactor = this.$el.find('.scale-factor');
            this.$svgWarning = this.$el.find('.svg-warning');
            this.$notWarning = this.$el.find('.not-warning');
            this.$downloadButton = this.$el.find('#downloadBtn');
            this.$batchDownloadButton = this.$el.find('#batchDownloadBtn');
            this.$saveButton = this.$el.find('#saveBtn');

            this.$fileName.attr('title', deps.translate(
                'FORBIDDEN_CHARACTERS_ERROR',
                // variable has an extra backslash which the user shouldn't see
                FORBIDDEN_CHARACTERS.replace("\\\\", "\\")
            ));
            this.$fileName.attr('pattern', VALIDATION_PATTERN);

            this.toggleDownloadButtonVisibility();

            if (this.defaultPreferredImageQuality) {
                this.$qualityPercent.val(this.defaultPreferredImageQuality);
                this.$qualityRange.val(parseInt(this.defaultPreferredImageQuality, 10));
            }

            // Only enable if feature is enabled for now.
            this.$scale.toggle(true);
            
            //update status of save maultiple based on the scale checkbox
            this.scaleEnabledChanged();

            return this;
        },
        
        handlePreferenceUpdate: function () {
            this.defaultExtension = PreferenceController.get("preferredFileExtension");
            this.defaultPreferredImageQuality = PreferenceController.get("preferredImageQuality");
        },
        
        handleKeydownOnPathInputs: function (e) {
            // Download on Enter
            if (e.keyCode === 13) {
                this.handleExportAsset();
            } else {
                this.removeErrorHighlight();
            }
        },
        
        handleTabOrdering: function (e) {
            var folderInput;
            // Tab back to Folder input, ignoring the rest
            if (e.keyCode === 9 && !e.shiftKey) {
                folderInput = this.$el.find('.' + this.folderNameInputClass);
                folderInput.focus();
                folderInput.select();
                e.preventDefault();
            }
        },
        
        downloadPSDExtractAsset: function (filepath, successFunc, failureFunc, options) {
            // Determine the type of file that needs to 
            // be downloaded.
            var imageFormat = "png";
            
            if (filepath.indexOf(".png") !== -1) {
                imageFormat = "png";
            } else if (filepath.indexOf(".jpg") !== -1) {
                imageFormat = "jpg";
            } else if (filepath.indexOf(".jpeg") !== -1) {
                imageFormat = "jpeg";
            } else if (filepath.indexOf(".svg") !== -1) {
                imageFormat = "svg";
            }
            
            var thePromise = DWPSDExtractManager.toDataURL(filepath, null, imageFormat, options);
            
            thePromise.then(successFunc, failureFunc);
        },
        
        toggleDownloadButtonVisibility: function () {
            // Do nothing for now. Download button should always be visible by default
        },
        
        createFinalDownloadPath: function (folderPath, layerName, fileExtension) {
            var pathSeparator = '';
            if (window.dwData.OsType === "MAC") {
                pathSeparator = ':';
            } else {
                pathSeparator = '\\';
            }
            
            // If separator is already added, then no need to add it again
            if (folderPath.charAt(folderPath.length - 1) === pathSeparator) {
                pathSeparator = '';
            }
            return (folderPath + pathSeparator + layerName + fileExtension);
        },
        
        getDefaultFileextension: function () {
            return this.defaultExtension || "png";
        },
        
        getErrorStringFromResponse: function (responseIndex) {
            if (responseIndex !== -1 && responseIndex < this.responseErrorStrings.length) {
                return this.responseErrorStrings[responseIndex];
            }
            return this.responseErrorStrings[0];
        },
        
        initiateDownload: function (folderPath, layerName, fileExtension, options) {
            var path = this.createFinalDownloadPath(folderPath, layerName, fileExtension),
                self = this,
                $folderPathInput = this.$el.find(".folder-name-input"),
                $filePathInput = this.$el.find(".file-name-input"),
                $btn = self.$el.find("#" + this.downloadButtonId),
                $saveMultipleBtn = self.$el.find("#" + this.batchDownloadButtonId),
                errorString;
            var downloadSuccessCallback = function () {
                graphite.events.trigger("extract-asset-download-success");
                if (options.scaleFactor && options.scaleFactor !== 1) {
                    graphite.events.trigger("asset-extracted-scaled", {scaleFactor: options.scaleFactor});
                }
                
                var imageQuality = parseInt(options.imageQuality, 10);
                if (imageQuality !== -1 && imageQuality < 100) {
                    graphite.events.trigger("asset-extracted-optimized");
                }
                
                if (options.isSourceLayersPanel) {
                    graphite.events.trigger("asset-download-layers-panel");
                } else if (options.isSourceCSSHudPsdPreview) {
                    graphite.events.trigger("asset-download-css-hud");
                }
                
            };
            var downloadFailureCallback = function (errorString, responseStatus) {
                if (responseStatus === Constants.Errors.UNKNOWN_FILE_WRITE_ERROR) {
                    window.graphite.events.trigger("file-write-error", "WRITE_FILE_FAILED_INVALID_PERMISSION", 'ERROR_FILE_WRITE_FAILED');
                } else if (responseStatus === 0) {
                    window.graphite.events.trigger("file-download-error", "DOWNLOAD_FAILED_DUE_TO_DISCONNECT", 'ERROR_DOWNLOAD_FAILED');
                } else {
                    window.graphite.events.trigger("file-download-error", "EXTRACTION_FAILED_DUE_TO_UNKNOWN_ERROR", 'ERROR_DOWNLOAD_FAILED');
                }
            };
            // TODO: validate inidividual folder/filename first
            var beginDownloadCallback = function (response) {
                if (response === self.responseCodes.indexOf("Response_Valid") ||
                        (response === self.responseCodes.indexOf("ErrorType_FILEEXISTS") &&
                            $btn.html() === deps.translate("REPLACE"))) {
                    
                    self.downloadPSDExtractAsset(path, downloadSuccessCallback, downloadFailureCallback, options);
                    
                    var fileFormatSelected = self.getFileFormat();
                    graphite.events.trigger("extract-asset-download-init", {formatSubEvent : [fileFormatSelected.toUpperCase()]});
                    self.removeErrorHighlight();
                    self.closePopup();
                } else if (response === self.responseCodes.indexOf("ErrorType_FILEEXISTS")) {
                    self.removeErrorHighlight();
                    $btn.html(deps.translate("REPLACE"));
                    errorString = self.getErrorStringFromResponse(response);
                    graphite.events.trigger("extract-asset-validation-error", deps.translate(errorString, layerName + fileExtension), false);
                    $btn.addClass("error-highlight");
                } else {
                    $folderPathInput.addClass("error-highlight");
                    $filePathInput.addClass("error-highlight");
                    errorString = self.getErrorStringFromResponse(response);
                    graphite.events.trigger("extract-asset-validation-error", deps.translate(errorString));
                }
            };
            
            var beginDownloadMultipleAssetsCallback = function (deviceTypes) {
                //if none of the device types are selected, then show extract prefs
                if (!deviceTypes || deviceTypes.length === 0) {
                    DWPSDExtractManager.displayExtractPrefs();
                    return;
                }
                var i, validationSuccess = true;
                options.deviceTypesPaths = [];
                for (i = 0; i < deviceTypes.length; ++i) {
                    if (deviceTypes[i]) {
                        var curResponse = deviceTypes[i].response;
                        if (curResponse === self.responseCodes.indexOf("Response_Valid") ||
                                (curResponse === self.responseCodes.indexOf("ErrorType_FILEEXISTS") &&
                                    $saveMultipleBtn.html() === deps.translate("REPLACE_MULTIPLE"))) {
                            options.deviceTypesPaths.push({
                                scale: deviceTypes[i].scale,
                                filepath: deviceTypes[i].filepath
                            });
                        } else if (curResponse === self.responseCodes.indexOf("ErrorType_FILEEXISTS")) {
                            self.removeErrorHighlight();
                            $saveMultipleBtn.html(deps.translate("REPLACE_MULTIPLE"));
                            errorString = self.getErrorStringFromResponse(curResponse);
                            graphite.events.trigger("extract-asset-validation-error", deps.translate("FILE_EXISTS_BATCH_EXTRACT_ERROR"));
                            $saveMultipleBtn.addClass("error-highlight");
                            validationSuccess = false;
                            break;
                        } else {
                            $folderPathInput.addClass("error-highlight");
                            $filePathInput.addClass("error-highlight");
                            errorString = self.getErrorStringFromResponse(curResponse);
                            graphite.events.trigger("extract-asset-validation-error", deps.translate(errorString));
                            validationSuccess = false;
                            break;
                        }
                    }
                }
                
                //if all filepaths validated successfully, then initiate download
                if (validationSuccess && options.deviceTypesPaths.length > 0) {
                    self.downloadPSDExtractAsset(path, downloadSuccessCallback, downloadFailureCallback, options);
                    var fileFormatSelected = self.getFileFormat();
                    graphite.events.trigger("extract-asset-download-init", {formatSubEvent : [fileFormatSelected.toUpperCase()]});
                    graphite.events.trigger("save-multiple-initiated");
                    var selectedTypes = options.deviceTypesPaths, selectedArray = [];
                    for (i = 0; i < selectedTypes.length; ++i) {
                        selectedArray.push("Selected:" + selectedTypes[i].scale);
                    }
                    graphite.events.trigger("batch-extract-scale", {dataGroup: selectedArray});
                    self.removeErrorHighlight();
                    self.closePopup();
                }
            };
            
            if ($folderPathInput.val() === "") {
                $folderPathInput.addClass("error-highlight");
                graphite.events.trigger("extract-asset-validation-error", deps.translate("ENTER_A_FOLDER"));
                return;
            } else {
                $folderPathInput.removeClass("error-highlight");
            }
            if ($filePathInput.val() === "") {
                $filePathInput.addClass("error-highlight");
                graphite.events.trigger("extract-asset-validation-error", deps.translate("ENTER_A_FILE_NAME"));
                return;
            } else {
                $filePathInput.removeClass("error-highlight");
            }
            
            if (options.isBatchExport) {
                DWPSDExtractManager.getFilePathsForMultipleAssetsDownload({
                    callback: beginDownloadMultipleAssetsCallback,
                    filePath: path
                });
            } else {
                DWPSDExtractManager.validatePathForExtractAssetDownload({
                    callback: beginDownloadCallback,
                    filePath: path
                });
            }
        },
        
        handleFolderBrowse: function () {
            var self = this,
                textFieldValue = self.$el.find('.' + self.folderNameInputClass).val(),
				initialBrowseDirectory = textFieldValue && textFieldValue.trim() !== "" ? textFieldValue : self.imageDownloadUrl;
			
            DWPSDExtractManager.browseForFolder({
                callback: function (path) {
					if (path !== "") {
						self.$el.find('.' + self.folderNameInputClass).val(path);
						self.removeErrorHighlight();
					}
                    self.$el.find('.' + self.folderNameInputClass).focus();
                },
                title: deps.translate("SELECT_FOLDER"),
                initialDirectory: initialBrowseDirectory
            });
        },
        
        closePopup: function () {
            BasePopupView.prototype.closePopup.apply(this, arguments);
            graphite.events.trigger("remove-error-notification");
        },
        
        updateSizeAndDescription: function () {
            var fileFormatSelected = this.getFileFormat();

            if (fileFormatSelected === "jpeg" || fileFormatSelected === "jpg") {
                this.$qualityLabel.html(deps.translate('OPTIMIZE'));
                this.$qualityBox.removeClass('quality-description');
                this.$qualityRange.css('display', 'block');
                this.$qualityPercent.css('display', 'block');
                this.$formatDescription.css('display', 'none');
                // DW specific
                this.$el.find('.optimize.clearfix').show();
                this.$el.find('#extension-text').text('.jpg');
            } else {
                this.$qualityBox.addClass('quality-description');
                this.$qualityRange.css('display', 'none');
                this.$qualityPercent.css('display', 'none');
                this.$formatDescription.css('display', 'block');
                // Update the description
                this.$formatDescription.html(this.description[fileFormatSelected]);
                // DW specific
                this.$el.find('.optimize.clearfix').hide();
                this.$qualityLabel.html("");
                this.$el.find('#extension-text').text('.png');
            }
            if (fileFormatSelected === 'svg' && this.bitmap) {
                this.$svgWarning.show();
                this.$svgWarning.css({
                    marginBottom: this.$notWarning.outerHeight(true) - this.$svgWarning.outerHeight() + 10
                });
                this.$notWarning.hide();
            } else {
                this.$svgWarning.hide();
                this.$notWarning.show();
            }
            if (this.baseName) {
                var fileName = DerivedAssetController.generateUniqueAssetName(this.baseName, fileFormatSelected);
                this.$fileName.val(fileName);
            }
        },
        
        removeEventListeners: function () {
            graphite.events.off(null, null, this);
            
            this.$el.off('.extractasset');
            this.$fileName.off('.extractasset');
            this.$qualityRange.off('.extractasset');
            this.$qualityPercent.off('.extractasset');
            this.$el.find("input.file-name").off('.extractasset');
            this.$el.removeData().unbind();
        },
        
        remove: function () {
            if (this.imageObj) {
                this.imageObj.src = "";
                this.imageObj = null;
            }
            this.undelegateEvents();
            this.unbind();
            this.stopListening();
            PreferenceController.off("change:Preferences", this.handlePreferenceUpdate, this);
            ExtractAssetView.prototype.remove.apply(this, arguments);
        },
        
        addHandlers: function () {
            var self = this;
            BasePopupView.prototype.addHandlers.apply(this, arguments);

            graphite.events.on('show-extract-asset-popup', this.handleShow, this);
            graphite.events.on('hide-extract-asset-popup', this.handleHide, this);

            this.$el.on('mousedown.extractasset', function (event) {
                event.stopPropagation();
            });

            this.$fileName.on('change.extractasset', function () {
                self.updateSizeAndDescription();
            });
            
            this.$fileFormat.on('change.extractasset', function () {
                self.updateSizeAndDescription();
            });

            this.$qualityRange.on('change.extractasset', function () {
                self.updatePercent(this.value);
            });

            this.$qualityPercent.on('change.extractasset', function () {
                self.updateRange(this.value);
            });

            this.$qualityPercent.on('keyup.extractasset', function () {
                self.updateRange(this.value);
            });

            //swallow key up events
            var fileNameInput = this.$el.find("input.file-name");
            fileNameInput.on('keyup.extractasset', function (event) {
                self.handleKeyUp(event);
                event.stopImmediatePropagation();
            });

            fileNameInput.on('keypress.extractasset', function (event) {
                if (event.which === 13) {
                    self.handleExportAsset();
                }
            });

            fileNameInput.change(function () {
                self.baseName = null;
            });
            graphite.events.on("selection-changed", this.closePopup, this);
        },
        
        setFileFormat: function (value) {
            value = value === "jpg" ? "jpeg" : value;
            this.$fileFormat.find('input[value=' + value + ']').prop("checked", true);
        },
        
        handleShow: function (params) {
			var self = this,
                title = this.$el.find('.title'),
                layer,
                isVector,
                i,
                ii;
            //If the user is offline, do nothing.
            if (DWPSDExtractManager.canEnableDownloadAssets()) {
                // If we're not logged in, don't allow extraction of multiple layers at once
                // Using deps.user() for now, assuming that will be the gate for multi extraction
                var selectedLayers = deps.utils.getCurrentPage() ? SelectionController.getSelectedLayers() :
                        SelectionController.getSelectedLayers().slice(0, 1);

                this.bitmap = false;
                for (i = 0, ii = selectedLayers.length; i < ii; i++) {
                    layer = selectedLayers[i];
                    isVector = layer.get('type') === 'textLayer' || layer.get('properties').get('shape');
                    this.bitmap = this.bitmap || !isVector;
                }

                var layerModel = selectedLayers[0],
                    layerName = layerModel.get("layerName");
                this.selectedVisibleLayers = SelectionController.expandSelection(selectedLayers);
                
                if (layerModel && this.selectedVisibleLayers.length) {
                    this.deriveAssetDetailsFromLayer(layerModel);

                    if (this.selectedVisibleLayers.length === 1) {
                        this.$el.find(".title").html(deps.translate("FOLDER"));
                    } else {
                        this.$el.find(".title").html(deps.translate("SAVE_COUNT_LAYERS_AS_IMAGE", this.selectedVisibleLayers.length));
                    }
                    
                    layerName = layerName.replace(/\s+/g, "_");

                    this.updateSizeAndDescription();
                    this.populateDefaultFolder();
                    this.removeErrorHighlight();
                    //Multiple asset download options should not be shown in the tutorial PSD
                    var batchDownloadButtonsGroup =  this.$el.find("#" + this.batchDwnldBtnsGroupId);
                    if (batchDownloadButtonsGroup && !DWPSDExtractManager.isAssetBatchExtractAvailable()) {
                        batchDownloadButtonsGroup.css('visibility', 'hidden');
                    }
                    BasePopupView.prototype.handleShow.apply(this, arguments);
                    
                    // Focus the folder input by default
                    var folderInput = this.$el.find('.' + this.folderNameInputClass);
                    folderInput.focus();
                    folderInput.select();
                    
                    if (selectedLayers.length > 1) {
                        var canvas = this.$el.find("#sprite_preview")[0];
                        canvas.width = 52;
                        canvas.height = 40;
                        var context = canvas.getContext('2d');
                        if (this.imageObj) {
                            this.imageObj.src = "";
                        } else {
                            this.imageObj = new Image();
                        }

                        this.imageObj.onload = function () {
                            context.drawImage(self.imageObj, 0, 0);
                        };
                        this.imageObj.src = 'images/MultipleLayersPreview.svg';
                    } else {
                        SpriteSheetUtils.renderSpriteModel(this, layerModel, ".image-wrapper", '#sprite_preview', false, 52, 40);
                    }
                }
            } else if (params && params.type === 'edit') {
                title.html(deps.translate('EDIT_IMAGE_PROPERTIES'));

                this.deriveAssetDetailsFromAsset(DerivedAssetController.getMetadataForAsset(params.model));
                this.updateSizeAndDescription();
                this.updateFileNameValidity();
                BasePopupView.prototype.handleShow.apply(this, arguments);
            }
        },
        
        removeErrorHighlight: function () {
            this.$el.find('.' + this.folderNameInputClass).removeClass("error-highlight");
            this.$el.find('.' + this.fileNameInputClass).removeClass("error-highlight");
            this.$el.find('#' + this.downloadButtonId).removeClass("error-highlight");
            this.$el.find('#' + this.downloadButtonId).html(deps.translate("SAVE"));
            this.$el.find('#' + this.batchDownloadButtonId).removeClass("error-highlight");
            this.$el.find('#' + this.batchDownloadButtonId).html(deps.translate("SAVE_MULTIPLE"));
            graphite.events.trigger("remove-error-notification");
        },
        
        populateDefaultFolder: function () {
            var self = this,
                documentsFolder = "";
            
            if (window.dwData && window.dwData.userDocumentsPath) {
                documentsFolder = window.dwData.userDocumentsPath;
            }
            DWPSDExtractManager.getImageDownloadLocation({
                callback: function (downloadPaths) {
                    self.imageDownloadPath = downloadPaths.siterootPath;
                    self.imageDownloadUrl = downloadPaths.siterootUrl;
                    self.$el.find('.' + self.folderNameInputClass).val(self.imageDownloadPath);
                },
                defaultFolder: documentsFolder,
                returnPath: true
            });
        },
        
        normalizeFileName: function (name) {
            return DWPSDExtractManager.normalizeFileName(name);
        },

        showBatchExportSettings: function () {
            //show extract preferences
            graphite.events.trigger("show-settings-clicked");
            DWPSDExtractManager.displayExtractPrefs();
        },

        handleBatchExportAsset: function () {
            this.handleExportAsset(true);
        },
        
        handleExportAsset: function (isBatchExport) {
            //default image quality
            var imageQuality = -1,
                scaleFactor = this.$scaleEnabled.prop("checked") && !this.$scale.hasClass("incompatible") ?
                        parseFloat(this.$scaleFactor.val()) : null,
                fileName,
                folderPath,
                extension = this.$el.find('#extension-text').text();
            
            if (!extension) {
                extension = this.defaultExtension;
            }

            var fileFormatSelected = this.getFileFormat();
            if (fileFormatSelected === "jpeg") {
                //image quality slider for jpeg format
                imageQuality = this.$qualityPercent.val();
                if (imageQuality === -1) {
                    imageQuality = null;
                }
            }

            fileName = this.normalizeFileName(this.$el.find('.' + this.fileNameInputClass).val());
            folderPath = this.$el.find('.' + this.folderNameInputClass).val();
            
            var options = {
                fileformat: this.getFileFormat(),
                imageQuality: imageQuality,
                scaleFactor: scaleFactor,
                isSourceLayersPanel: (this.source.hasClass("asset-button")),
                isSourceCSSHudPsdPreview : (this.source.hasClass("measurementElementAssetExtract")),
                isBatchExport : (isBatchExport === true)
            };
            
            this.initiateDownload(folderPath, fileName, extension, options);
        }
    });

    return DwExtractAssetView;
});
