/*
 * 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, window: true, document: true*/

define([
    'jquery',
    'underscore',
    'backbone',
    'ccweb.files.extract/Constants',
    'ccweb.files.extract/controllers/DetailsController',
    'ccweb.files.extract/controllers/ZoomController',
    'ccweb.files.extract/models/LayerModel',
    'ccweb.files.extract/models/LayerModelMap',
    'ccweb.files.extract/models/ColorUsageModel',
    'ccweb.files.extract/models/TextStyleUsageModel',
    'ccweb.files.extract/models/GradientUsageModel',
    'ccweb.files.extract/utils/StyleUtil',
    'parfait/SelectionController',
    'ccweb.files.extract/utils/MeasurementUtil'
], function ($, _, Backbone, Constants, DetailsController, ZoomController, LayerModel,
        LayerModelMap, ColorUsageModel, TextStyleUsageModel, GradientUsageModel,
        StyleUtil, SelectionController, MeasurementUtil) {
    'use strict';
    
    var DwSelectionController = $.extend(SelectionController, {
        selectItemAtPoint: function (clientX, clientY, addToSelection) {
            var hitItem = (clientX !== -1 && clientY !== -1) ? this.itemAtPoint(clientX, clientY) : null;
            this.changeSelection([hitItem], addToSelection, true);
            var hoverArray = hitItem !== null ? [hitItem] : [];
            graphite.events.trigger('item-hovered-over', hoverArray, true);
        },
        
        updateStylesForSelection: function () {
            var selectedLayers = this.getSelectedLayers(),
                extractedStyles = this.psdModel.get('extractedStyles') ||
                    {colors: [], textStyles: [], gradients: [], models: []},
                newUsageModels;

            if (selectedLayers.length) {
                var usageModels = {
                    colors: [],
                    textStyles: [],
                    gradients: []
                };

                $.each(selectedLayers, function (index, value) {
                    newUsageModels = value.getUsageModels();
                    value.combineUsageModels(usageModels, newUsageModels);
                });

                extractedStyles = {
                    colors: usageModels.colors,
                    textStyles: usageModels.textStyles,
                    gradients: usageModels.gradients,
                    models: selectedLayers
                };
            }

            var arrayToCheck;
            if (DetailsController.get('selectedInspectItem') instanceof ColorUsageModel) {
                arrayToCheck = extractedStyles.colors;
            } else if (DetailsController.get('selectedInspectItem') instanceof TextStyleUsageModel) {
                arrayToCheck = extractedStyles.textStyles;
            } else if (DetailsController.get('selectedInspectItem') instanceof GradientUsageModel) {
                arrayToCheck = extractedStyles.gradients;
            }

            if (arrayToCheck) {
                var found = false;
                $.each(arrayToCheck, function (index, value) {
                    if (StyleUtil.areUsageStylesEqual(value, DetailsController.get('selectedInspectItem'))) {
                        DetailsController.set('selectedInspectItem', value);
                        found = true;
                        return false;
                    }
                    return true;
                });

                if (!found) {
                    DetailsController.setSelectedInspectItem(null);
                }
            }

            this.set('extractedStylesInSelection', extractedStyles);

        },
        
        //***** HitTest Methods *****/
        itemAtPoint: function (clientX, clientY) {
            var hitItem = null;
            var id,
                root,
                layerCollection,
                i,
                layerItem,
                psdPt;

            for (id in this.focusMap) {
                if (this.focusMap.hasOwnProperty(id)) {
                    root = this.focusMap[id];

                    if (root !== null) {
                        layerCollection = root.get('layerCollection');
                        if (layerCollection) {
                            for (i = layerCollection.length - 1; i >= 0; i--) {
                                layerItem = layerCollection.at(i);
                                psdPt = this.convertClientPtToPSDPt(clientX, clientY);
                                hitItem = this.hitTestItem(layerItem, psdPt.x, psdPt.y, true);
                                if (hitItem) {
                                    break;
                                }
                            }
                        }
                        if (hitItem) {
                            break;
                        }

                    }
                }
            }

            return hitItem;
        },
        
        pixelHit: function (canvas, x, y, bounds) {
            var hit = false,
                left = bounds.left,
                top = bounds.top,
                imgData,
                i;

            if (!this.offscreenContext) {
                this.offscreenCanvas = $('<canvas/>')[0];
                // Note 257x256 here instead of 1x1. For now we are working around
                // a chrome issue https://code.google.com/p/chromium/issues/detail?id=382588
                this.offscreenCanvas.width = 257;
                this.offscreenCanvas.height = 256;
                this.offscreenContext = this.offscreenCanvas.getContext('2d');
                this.offscreenContext.imageSmoothingEnabled = false;
            }

            if (this.clipLayersToImage) {
                left = Math.max(left, 0);
                top = Math.max(top, 0);
            }

            this.offscreenContext.clearRect(0, 0, 1, 1);
            this.offscreenContext.drawImage(canvas, x - left, y - top, 1, 1, 0, 0, 1, 1);

            imgData = this.offscreenContext.getImageData(0, 0, 1, 1);

            for (i = 0; i < imgData.data.length; i += 4) {
                if (imgData.data[i + 3] > 0) {
                    hit = true;
                    break;
                }
            }
            return hit;
        },
        
        convertClientPtToPSDPt: function (clientX, clientY) {
            var psdPt = {},
                $results = $('.psd-preview-view');
            var documentOffset = $results.find('.preview-container').offset();
            var paddingTop = $results.find('.preview-container').css('padding-top');
            var paddingLeft = $results.find('.preview-container').css('padding-left');

            psdPt.x = clientX - documentOffset.left - parseInt(paddingLeft, 10);
            psdPt.y = clientY - documentOffset.top - parseInt(paddingTop, 10);

            psdPt = ZoomController.zoomPoint(psdPt, true);

            return psdPt;
        },
        
        enableDropperTool: function () {
            if (DetailsController.get('activeTool') === Constants.Tool.DROPPER) {
                this.disableDropperTool();
                return;
            }

            DetailsController.changeActiveTool(Constants.Tool.DROPPER);
            this.selectItemAtPoint(-1, -1, false);
            DetailsController.setSelectedInspectItem(null);
            $('.extract-plugin').addClass('dropper-tool');
            graphite.events.trigger('dropperStart');
        },

        disableDropperTool: function () {
            DetailsController.changeActiveTool(Constants.Tool.SELECT_DIRECT);
            $('.extract-plugin').removeClass('dropper-tool');
            graphite.events.trigger('dropperStop');
        }

    });
    
    return DwSelectionController;
});