/*
 * 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*/

define([
    "underscore",
    "backbone"
], function (_, Backbone) {
    "use strict";
    var CopyCssPopupModel = Backbone.Model.extend({

        defaults: {
            cssArray: [],
            filtered: [],
            inline: [],
            cssPropertiesData: {
                backgroundCss: [],
                layoutCss: [],
                inlineCss: [],
                textCss: [],
                borderCss: [],
                other: []
            },
            propertyGroups: {
                background: ['background', 'background-attachment', 'background-blend-mode', 'background-clip', 'background-color', 'background-image', 'spread',
                            'background-origin', 'background-position', 'background-position-x', 'background-position-y', 'background-repeat', 'background-repeat-x',
                            'background-repeat-y', 'background-size', 'inset', 'box-shadow', 'h-shadow', 'v-shadow', 'blur', 'spread'],
                layout:     ['width', 'height', 'min-width', 'min-height', 'max-width', 'max-height', 'display', 'box-sizing', 'margin', 'padding', 'position',
                            'float', 'clear', 'overflow-x', 'overflow-y', 'visibility', 'z-index', 'opacity'],
                text:       ['color', 'font-family', 'font-style', 'font-variant', 'font-weight', 'font-size', 'line-height', 'text-align', 'text-decoration',
                            'text-indent', 'h-shadow', 'v-shadow', 'blur', 'text-transform', 'letter-spacing', 'word-spacing', 'white-space', 'vertical-align',
                            'list-style-postition', 'list-style-image', 'list-style-type'],
                border:     ['border', 'border-bottom', 'border-bottom-color', 'border-bottom-style', 'border-bottom-width', 'border-color', 'border-left', 'border-left-color',
                             'border-left-style', 'border-left-width', 'border-right', 'border-right-color', 'border-right-style', 'border-right-width', 'border-style',
                             'border-top', 'border-top-color', 'border-top-style', 'border-top-width', 'border-width', 'border-radius', 'border–collapse', 'border-spacing'],
                other:      ['transform']

            }
        },

        initialize: function () {
            this.createCssStructures();
        },
        
        findMatchingCssGroup: function (group, property) {
            var propertyGroups = this.get('propertyGroups'),
                groupItemsList = propertyGroups[group];
            
            return groupItemsList.some(function (groupItem) {
                return (property.indexOf(groupItem) !== -1);
            });
        },
        
        filterInlineCss: function () {
            var filtered = [],
                inline = [],
                inlineblock = [],
                isinline = false,
                inlineStyleLabel = 'Inline Style';
            
            this.get('cssArray').forEach(function (cssItem) {
                if (cssItem.property) {
                    if (isinline) {
                        inlineblock.push(cssItem);
                    } else {
                        filtered.push(cssItem);
                    }
                } else {
                    if (cssItem.label.indexOf(inlineStyleLabel) !== -1) {
                        isinline = true;
                    } else if (cssItem.label === '') {
                        isinline = false;
                    }
                    if (inlineblock.length) {
                        inline.push(inlineblock);
                        inlineblock = [];
                    }
                }
            });
            
            this.set('filtered', filtered);
            this.set('inline', inline);
        },
        
        groupCssBlocks: function () {
            var filtered = this.get('filtered'),
                cssPropertiesData = this.get('cssPropertiesData'),
                self = this;
            
            filtered.forEach(function (cssItem) {
                if (self.findMatchingCssGroup('background', cssItem.property)) {
                    cssPropertiesData.backgroundCss.push(cssItem);
                } else if (self.findMatchingCssGroup('border', cssItem.property)) {
                    cssPropertiesData.borderCss.push(cssItem);
                } else if (self.findMatchingCssGroup('text', cssItem.property)) {
                    cssPropertiesData.textCss.push(cssItem);
                } else if (self.findMatchingCssGroup('layout', cssItem.property)) {
                    cssPropertiesData.layoutCss.push(cssItem);
                } else if (self.findMatchingCssGroup('other', cssItem.property)) {
                    cssPropertiesData.other.push(cssItem);
                } else {
                    // A property not matching anywhere is pushed into text. 
                    // This should never happen though
                    cssPropertiesData.textCss.push(cssItem);
                }
            });
            
            cssPropertiesData.inlineCss = this.get('inline');
            
        },
        
        clearOldData: function () {
            this.set('cssPropertiesData', {
                backgroundCss: [],
                layoutCss: [],
                inlineCss: [],
                textCss: [],
                borderCss: [],
                other: []
            });
        },
        
        getAllCssItemsLength: function () {
            var cssPropertiesData = this.get('cssPropertiesData'),
                count = 0;
            
            Object.keys(cssPropertiesData).forEach(function (key) {
                if (key !== 'inlineCss') {
                    count += cssPropertiesData[key].length;
                } else if (cssPropertiesData[key].length) {
                    // Count the length of the first inline block only
                    // We do not want to count them all since the length
                    // we calculate is the selectable length in the copy 
                    // popup. A property can be selected in only one inline 
                    // block at once
                    count += cssPropertiesData[key][0].length;
                }
            });
            return count;
        },
        
        removeAndMergeInlineWithText: function () {
            var cssPropertiesData = this.get('cssPropertiesData'),
                textCss = cssPropertiesData.textCss,
                inline = [textCss].concat(cssPropertiesData.inlineCss),
                newTextCss = [],
                newInline = [],
                newInlineBlock = [],
                common;
            
            function findinInline(inline, searchCssElement) {
                var cssMatchedCounter = 0,
                    propertyMatchedCounter = 0;
                inline.forEach(function (inlineBlock, i) {
                    inlineBlock.forEach(function (cssElement) {
                        if (searchCssElement.property === cssElement.property) {
                            propertyMatchedCounter++;
                            if (searchCssElement.value === cssElement.value) {
                                cssMatchedCounter++;
                            }
                        }
                    });
                });
                return {
                    cssMatchedCounter: cssMatchedCounter,
                    propertyMatchedCounter: propertyMatchedCounter
                };
                //return locatedIn === inline.length;
            }
            // First remove common css from inline
            inline.forEach(function (inlineBlock, i) {
                newInlineBlock = inlineBlock.filter(function (inlineCssElement) {
                    var cssMatchedData = findinInline(inline, inlineCssElement);
                    common = cssMatchedData.cssMatchedCounter === inline.length;
                    // Adding the OR condition for properties like text-shadow which don't appear
                    // in an inline block. Even though it is not a 'common' property between
                    // multiple inline blocks, we must classify it as a common property.
                    // Text-shadow is converted from drop shadow effect in PS and apparently
                    // it can never be applied differently within a layer and consequently 
                    // never be an inline property. In case there turn out to more properties 
                    // like text shadow, this change should handle it
                    if ((common || cssMatchedData.propertyMatchedCounter === 1) && !i) {
                        newTextCss.push(inlineCssElement);
                    }
                    return ((common === false) && !((cssMatchedData.propertyMatchedCounter === 1) && (i === 0)));
                });
                newInline.push(newInlineBlock);
            });
            cssPropertiesData.inlineCss = newInline;
            cssPropertiesData.textCss = newTextCss;
        },
        
        createCssStructures: function () {
            var cssArray = this.get('cssArray');
            
            this.clearOldData();
            this.filterInlineCss(cssArray);
            this.groupCssBlocks();
            this.removeAndMergeInlineWithText();
        }
    });

    return CopyCssPopupModel;

});