
/*
 * 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 */
/*global define: true, graphite: true, window: true, setTimeout: true, XMLHttpRequest: true*/

define([
    'jquery',
    'underscore',
    'backbone',
    'plugin-dependencies',
    'controllers/AuthController',
    'utils/TemplateUtil',
    'controllers/ThumbnailController',
    'controllers/ErrorMessageController'
], function ($, _, Backbone, deps, AuthController, TemplateUtil, ThumbnailController, ErrorMessageController) {
    "use strict";
    var AssetView = Backbone.View.extend({

        tagName: "article",
        className: "card-asset",

        initialize: function () {
            if (this.model.get("fileToLoad") === undefined) {
                var date = new Date(this.model.attributes.created);
                this.model.attributes.date = window.dwPSDExtractManager.getFormattedDateTime(date);
                date = null;

                // var asset = this.model.get("metadata").asset;
                // if (!asset.hasOwnProperty('dimension')) {
                //     var xmp = this.model.get("metadata").xmp;
                //     if (xmp && xmp.hasOwnProperty('exif:PixelXDimension') && xmp.hasOwnProperty('exif:PixelYDimension')) {
                //         asset.dimension = [{'width': xmp['exif:PixelXDimension'], 'height': xmp['exif:PixelYDimension']}];
                //     } else {
                //         asset.dimension = [{'width': '???', 'height': '???'}];
                //     }
                // }
            }

            this.listenTo(this.model, "change:uploadProgress", this.updateProgress);
            this.listenTo(this.model, 'destroy', this.remove);

            var workerId = this.getGraphiteWorker();
            if (workerId) {
                var prog = {'status' : deps.translate("PROCESSING"),
                            'percentage' : 0,
                            'nextStep' : deps.translate("ALMOST_READY"),
                            'assetID' : this.model.get("id"),
                            'workerID' : workerId};
                this.model.set("fileToLoad", { "name" : this.model.get('metadata').asset.fileName });
                this.model.set("uploadProgress", prog);
            }

            this.render();
            this.addHandlers();
        },

        render: function () {
            try {
                var tmplId;
                if (this.model.get("fileToLoad") !== undefined) {
                    if (this.model.get('type') === 'application/vnd.adobe.directory+json') {
                        this.$el.addClass("asset-folder");
                        tmplId = "#asset-folder-view-template";
                    } else {
                        tmplId = "#asset-view-loading-template";
                    }
                } else {
                    if (this.model.get('type') === 'application/vnd.adobe.directory+json') {
                        this.$el.addClass("asset-folder");
                        tmplId = "#asset-folder-view-template";
                    } else if (this.model.get('type') === 'image/vnd.adobe.photoshop/upload') {
                        tmplId = "#asset-upload-view-template";
                    } else {
                        tmplId = "#asset-view-template";
                        //Call out to see if this file is still processing. This can happen if the UI is refreshed
                        //while one or more PSDs are being processed.
                        //this.checkStatus();
                    }
                }
                var el = this.$el;
                el.html(TemplateUtil.createTemplate(tmplId, this.model.toJSON()));

                var elem = el.find(".assetThumbnail");
                if (elem[0]) {
                    ThumbnailController.drawThumbnail(this.model, elem[0]);
                }

                if (this.getGraphiteWorker()) {
                    this.$('.image-wrapper-progress').removeClass("asset-uploading").addClass("asset-processing");
                    this.$('#progressbar').removeClass("progressbar-uploading").addClass("progressbar-processing");
                }

            } catch (err) {
                console.log("Failed to render thumb for:" + this.model.attributes.name);
            }
            return this;
        },
        
        assetClickHandler: function (event) {
            var self = event.data.self;
            if (AuthController.isLoggedIn()) {
                if (!self.model.get("uploadProgress")) {
                    if (self.model.attributes.type === "application/vnd.adobe.directory+json") {
                        var location = Backbone.history.fragment || "files";
                        Backbone.history.navigate(location + "/" + self.model.get("name"), true);
                    } else if (self.model.attributes.type === "image/vnd.adobe.photoshop") {
                        var url = "asset/psd/" + self.model.get("id").replace(/\//g, "_") + "/" + self.model.get("md5").replace(/\//g, "_").replace(/\,/g, "_") + "/" + (Backbone.history.fragment || "files");
                        url = url +  "/" + self.model.get("name");
                        url = url.replace(/\/\//g, "/"); // remove dupe slashes
                        url = encodeURI(url);
                        Backbone.history.navigate(url, true);
                    } else if (self.model.attributes.type === "image/vnd.adobe.photoshop/upload") {
                        $('#gridContainer').find('input[name="uploadPSD"]').trigger('click');
                        return false;
                    }
                }
            } else {
                // DPO - I can't work out when or how this method gets fired.
                // There was an alert here before. This would never get shown, because it's not an alert.
                graphite.events.trigger('load-alert', deps.translate("NO_LONGER_LOGGED_IN_LOGIN_AGAIN"));
                window.location.href = window.location;
            }
        },
        
        addHandlers : function () {
            var that = this;
            this.$el.mouseenter(function () {
                $(that.el).find(".del-button").css("visibility", "visible");
                $(that.el).find(".del-button").click(function (event) {
                    graphite.serverAPI.deleteAsset(that.model.id,
                        that.handleDeleteSuccess,
                        that.handleDeleteError,
                        that);
                    event.stopImmediatePropagation();
                });
            });

            this.$el.mouseleave(function () {
                $(that.el).find(".del-button").css("visibility", "hidden");
            });

            this.$el.off('click', this.assetClickHandler).on('click', { self : this }, this.assetClickHandler);
        },

        handleDeleteSuccess: function () {
            console.log("successfully deleted assetId = " + this.model.id);
            this.remove();
            graphite.events.trigger('update-asset-list-view');
        },


        handleDeleteError: function (xhr) {
            if (xhr.status === 401) {
                graphite.events.trigger("reauthenticate");
            }
        },

        updateProgress : function () {
            this.callCount++;
            //console.log("AssetView.updateProgress(): " + this.model.id);
            var progress = this.model.get("uploadProgress");
            if (progress) {
                if (progress.status === deps.translate("PROCESSING")) {
                    //remove the uploading class , replace it with processing class
                    //console.log("PROGRESS_PROCESSING ***********************");
                    //this.$('.image-wrapper-progress').removeClass("asset-uploading");
                    this.$('#progressbar').removeClass("progressbar-uploading");
                    this.model.unset('uploadProgress');
                }
                var perc = '';
                if (progress.percentage) {
                    perc = Math.floor(progress.percentage) + "%";
                    this.$('#progressbar').width(perc);
                }
                
                this.$('#uploadStep').text(progress.status + " " + perc);
                
                if (progress.nextStep) {
                    this.$('#nextStep').text(progress.nextStep);
                }
                //console.log("updateProgress(), workerId = " + progress.workerID);
                if (progress.workerID) {
                    graphite.serverAPI.setWorkerOnAsset(progress.workerID, progress.assetID);
                    this.checkWorkerProgress(progress.workerID, progress.assetID);
                }
            }
        },


        checkWorkerProgress: function (workerId, assetId) {
            var that = this,
                thatWorker = workerId,
                thatAsset = assetId;

            function successCallback(response) {
                var json = JSON.parse(JSON.parse(response.responseText)),
                    progress = json.progress || 0,
                    status = null,
                    params,
                    statusText = "";

                if (json.results) {
                    status = json.results.status;
                }

                status = status || json.status || "Unknown";

                //console.log("worker status = " + status);
                //console.log("worker progress = " + progress);

                // TODO needs LOC
                if (status === "success") {
                    that.model.set("processFinished", Date.now());

                    //send the processed event
                    params = {};
                    params.filesize = that.model.get("fileSize");
                    params.processDuration = that.model.get("processFinished") - that.model.get("processStarted");
                    params.totalDuration = that.model.get("processFinished") - that.model.get("uploadStarted");
                    graphite.events.trigger('processed', params);

                    statusText = deps.translate("PROCESSING");
                    that.getModelData(thatAsset);

                } else if (status === "queued") {
                    statusText = deps.translate("QUEUED");
                    setTimeout(function () { that.checkWorkerProgress(thatWorker, thatAsset); }, 1000); // Ping the server for the status again
                } else if (status === "failed") {
                    //send the proccessedFailed event
                    params = {};
                    params.fileSize = that.model.get("fileSize");
                    params.errorCode = json.errorCode;
                    params.errorMessage = json.errorMessage;
                    graphite.events.trigger('processing-failed', params);

                    graphite.events.trigger('load-alert', ErrorMessageController.getErrorMessageForWorkerResult(json, that.model.get("fileToLoad").name));
                    that.model.id = thatAsset;

                    // Go ahead and delete it. It's not going to get better.
                    graphite.serverAPI.deleteAsset(that.model.id,
                        that.handleDeleteSuccess,
                        that.handleDeleteError,
                        that);

                    that.model.destroy();
                } else {
                    statusText = deps.translate("PROCESSING");
                    setTimeout(function () { that.checkWorkerProgress(thatWorker, thatAsset); }, 1000); // Ping the server for the status again
                }
                that.setProcessingProgressPercent(progress, statusText);
            }

            function errorCallback(resp) {
                that.getModelData(thatAsset);
            }
            graphite.serverAPI.getWorkerStatus(workerId, successCallback, errorCallback, this);
        },

        getModelData: function (assetId) {
            var that = this,
                thatAssetId = assetId;

            function successCallback(response) {
                var data = JSON.parse(response.responseText);
                // remove the graphite worker so we don't try to get the progress again
                graphite.serverAPI.setWorkerOnAsset(null, thatAssetId);

                if (data.hasOwnProperty('custom') && data.custom.hasOwnProperty('graphiteWorker')) {
                    delete data.custom.graphiteWorker;
                }
                var modelData = { 'id' : thatAssetId,
                                  'updated' : data.asset.created,
                                  'created' : data.asset.created,
                                  'mimeType' : data.asset.mimeType,
                                  'metadata' : data };

                that.model.clear();
                that.model.set(modelData);
                that.initialize();
            }

            graphite.serverAPI.getAssetInfo(assetId, successCallback, null, this);
        },


        setProcessingProgressPercent: function (progress, statusText) {
            var perc = Math.floor(progress) + "%";
            //console.log("setProcessingProgressPercent: " + statusText + " " + perc);
            this.$('#uploadStep').text(statusText + " " + perc);
            this.$('#progressbar').width(perc);
        },
        
        remove: function () {
            this.stopListening();
            this.undelegateEvents();
            this.$el.removeData().unbind();
			this.$el.empty();
            graphite.events.off(null, null, this);
            Backbone.View.prototype.remove.apply(this, arguments);
        },
        
        setProcessingView: function () {
            var tmplId = "#asset-view-loading-template";
            var el = this.$el;
            if (this.model.get("fileToLoad") === undefined) {
                this.model.set("fileToLoad", {name: this.model.get("metadata").asset.fileName});
            }

            var tmpl = TemplateUtil.createTemplate(tmplId, this.model.toJSON());
            el.html(tmpl);

            this.$('.image-wrapper-progress').removeClass("asset-uploading").addClass("asset-processing");
            this.$('#progressbar').removeClass("progressbar-uploading").addClass("progressbar-processing");
        },

        getGraphiteWorker: function () {
            var result = null;
            if (this.model.get("metadata") &&
                    this.model.get("metadata").custom &&
                    this.model.get("metadata").custom.graphiteWorker) {
                result = this.model.get("metadata").custom.graphiteWorker;
            }
            return result;
        }
    });
    return AssetView;
});
