/*
 * ADOBE CONFIDENTIAL
 *
 * Copyright (c) 2013 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, bitwise: true */
/*global define: true, graphite: true, Image: true, window: true*/

define([
    "jquery",
    "underscore",
    "backbone",
    'ccweb.files.extract/collections/DerivedAssetCollection',
    'ccweb.files.extract/models/DerivedAssetModel',
    'ccweb.files.extract/models/ExtractSettingsModel',
    'ccweb.files.extract/models/PSDSettingsModel',
    'ccweb.files.extract/Constants',
    'plugin-dependencies',
    "parfait/DerivedAssetController"
], function ($, _, Backbone, DerivedAssetCollection, DerivedAssetModel, ExtractSettingsModel,
              PSDSettingsModel, Constants, deps, DerivedAssetController) {
    "use strict";
    
    function deriveScaleFromSettings(type, designedAtMultiplier) {
        var scales = {
            LDPI: 0.75,
            MDPI: 1,
            TVDPI: 1.33,
            HDPI: 1.5,
            XHDPI: 2,
            XXHDPI: 3,
            XXXHDPI: 4
        };

        // This shouldn't happen
        if (!scales.hasOwnProperty(type)) {
            return 1;
        }

        return scales[type] / designedAtMultiplier;
    }

    function deriveNameFromSettings(name, suffix) {
        var extIndex = name.lastIndexOf('.');

        suffix = suffix || '';

        if (extIndex !== -1) {
            return name.substr(0, extIndex) + suffix;
        } else {
            return name + suffix;
        }
    }
        
    var DwDerivedAssetController = $.extend(DerivedAssetController, {
        registerDerivedAsset: function (psdModel, model, descriptor) {
            var self = this,
                asset = new DerivedAssetModel({
                    name: model.get('name'),
                    scale: descriptor.scale,
                    layerCompId: descriptor.layerCompId,
                    originatingLayers: descriptor.layerIds,
                    encodingType: descriptor.encodingType,
                    encodingQualityFactor: descriptor.encodingQualityFactor,
                    psdModified: psdModel.get('modified')
                });

            graphite.serverAPI.updateAssetData(this.psdGuid,
                'extract_asset_catalog',
                function (dataList) {
                    self.assetCatalog.reset(dataList);
                    var dups = self.assetCatalog.where({name: model.get('name')});
                    _.each(dups, function (model) {
                        self.assetCatalog.remove(model);
                    });
                    self.assetCatalog.push(asset);
                    return self.assetCatalog.toJSON();
                },
                function (response) {
                    self.assetCatalogVersion = response.etag;
                    self.assetCatalog.reset(response.data);
                    self._checkForRefresh(response);
                    graphite.events.trigger('batch_extract_start');
                    self.applyExportSettings(asset);
                },
                function (response) {
                    // recover from error
                    console.log('Failure updating derived asset metadata (append).');
                },
                null);
        },

        _unregisterDerivedAsset: function (asset) {
            var self = this;
            graphite.serverAPI.updateAssetData(this.psdGuid,
                'extract_asset_catalog',
                function (dataList) {
                    self.assetCatalog.reset(dataList);
                    var models = self.assetCatalog.where({name: asset.get('name')});
                    _.each(models, function (model) {
                        self.assetCatalog.remove(model);
                    });
                    return self.assetCatalog.toJSON();
                },
                function (response) {
                    self.assetCatalogVersion = response.etag;
                    self.assetCatalog.reset(response.data);
                    self._checkForRefresh(response);
                },
                function (response) {
                    // recover from error
                    console.log('Failure updating derived asset metadata (remove).');
                },
                null);
        },
        
        exportAsset: function (layerModels, directDownload, assetName, imageFormat, quality, scaleFactor, psdModel,
                               completeCallback, errorCallback, context) {
            var psdGuid,
                layerIds = [],
                iImageQuality = parseInt(quality, 10),
                i,
                queryString = '',
                joiner = '?',
                localContent = psdModel.get('localContent');

            for (i = 0; i < layerModels.length; i++) {
                layerIds.push(layerModels[i].get('layerId'));
            }
            // Handle request to extract from marketing PSD.
            if (localContent) {
                queryString = '';
                psdGuid = psdModel.get('id');
                queryString = queryString + joiner + 'layerIds=' + layerIds.join(',');
                joiner = '&';
                queryString = queryString + joiner + 'encodingType=' + imageFormat;
                queryString = queryString + joiner + 'encodingQualityFactor=' + iImageQuality;
                queryString = queryString + joiner + 'assetName=' + encodeURIComponent(assetName);

                //create a iframe to download the asset
                if (localContent) {
                    this.queueDownload('/api/v1/localcontent/' + psdGuid + '/derived' + queryString);
                } else {
                    this.queueDownload('/api/v1/psd/' + psdGuid + '/asset/derived' + queryString);
                }
                return;
            }

            iImageQuality = parseInt(quality, 10);

            //generate unique asset name
            if (!deps.utils.hasFeature('extract_batch')) {
                assetName = this.generateUniqueAssetName(assetName, imageFormat);
            }

            var jsonPostObject = {
                layerIds: layerIds,
                encodingType: imageFormat,
                encodingQualityFactor: iImageQuality,
                psdGuid: psdModel.get('id'),
                scale: scaleFactor,
                layerCompId: psdModel.get('layerCompId'),
                noCache: $.now(),
                assetName: assetName
            };

            var that = this;

            function onSuccess(data) {
                var response = JSON.parse(data.responseText);

                if (directDownload) {
                    that.queueDownload(graphite.serverAPI.getDerivedDownloadURL(response.id, response.name));
                } else {
                    /**** HACK start ****/
                    var model = new DerivedAssetModel();

                    if (response.metadata && response.metadata.asset) {
                        response.name = response.metadata.asset.fileName;
                    }

                    model.attributes = model.parse(response);

                    // Replace if duplicate
                    var origModels = that.derivedAssetCollection.where({name: model.get('name')});
                    if (origModels && origModels.length) {
                        that.derivedAssetCollection.remove(origModels);
                    }

                    that.derivedAssetCollection.add(model);

                    if (deps.utils.hasFeature('extract_batch')) {
                        // Register the extracted asset with our asset catalog.
                        that._registerDerivedAsset(psdModel, model, jsonPostObject);
                    }

                    /**** HACK end ****/
                }
                if (completeCallback) {
                    completeCallback.apply(context, [data]);
                }
            }

            function onError(errMsg) {
                graphite.events.trigger('assetExtractionFailure', {});
                if (errorCallback) {
                    errorCallback.apply(context, [errMsg]);
                }
            }

            graphite.serverAPI.createDerivedAsset(jsonPostObject, directDownload, onSuccess, onError, this);
        },
        
        deleteDerivedAsset: function (model, successHandler, errorHandler, context) {
            var self = this;
            if (deps.utils.hasFeature('extract_batch')) {
                self._unregisterDerivedAsset(model);
                successHandler.apply(context, [model]);
            } else {
                graphite.serverAPI.deleteDerivedAsset(
                    model.get('guid'),
                    function (data) {
                        successHandler.apply(context, [data]);
                    },
                    function (jqXHR) {
                        errorHandler.apply(context, [jqXHR]);
                    }
                );
            }
        },
        
        applyExportSettings: function (assetEntry) {
            var self = this,
                theCatalog = assetEntry ? new Backbone.Collection([assetEntry]) : self.assetCatalog,
                batchJobData = {
                    psdGuid: this.psdGuid,
                    jobs: [],
                    folderNames: []
                };

            self.deviceExtractSettings.each(function (settingValue) {
                if (settingValue.get('checked')) {
                    batchJobData.folderNames.push(settingValue.get('folder'));
                    theCatalog.each(function (catalogValue) {
                        var jobData = {
                            layerIds: catalogValue.get('originatingLayers'),
                            encodingType: catalogValue.get('encodingType'),
                            encodingQualityFactor: catalogValue.get('encodingQualityFactor'),
                            scale: deriveScaleFromSettings(settingValue.get('type'), PSDSettingsModel.get('designedAtMultiplier')),
                            assetName: deriveNameFromSettings(catalogValue.get('name'), settingValue.get('suffix')),
                            outputTarget: settingValue.get('folder')
                        };
                        if (catalogValue.get('layerCompId')) {
                            jobData.layerCompId = catalogValue.get('layerCompId');
                        }

                        batchJobData.jobs.push(jobData);
                    });
                }
            });

            if (batchJobData.jobs.length) {
                graphite.serverAPI.batchCreateDerivedAssets(
                    batchJobData,
                    function (goodStatus) {
                        graphite.events.trigger('batch_extract_complete');
                    },
                    function (badStatus) {
                        graphite.events.trigger('batch_extract_complete_error');
                    },
                    this
                );
            } else {
                graphite.events.trigger('batch_extract_cancelled');
            }
        }
    });
    return DwDerivedAssetController;
});
