/*
   Copyright 2010 Hanov Solutions Inc. All Rights Reserved

   steve.hanov@gmail.com
 */

/** @constructor */
function SetPropertyAction( view, nodes, name, value )
{
    this.view = view;
    this.nodes = nodes;
    this.name = name;
    this.value = value;
    this.oldValues = [];

    for ( var i = 0; i < this.nodes.length; i++ ) {
        var node = this.nodes[i];
        if ( this.name in node ) {
            this.oldValues[i] = node.getProperty( this.name );
        }
    }
}

SetPropertyAction.prototype = 
{
    execute: function()
    {
        for ( var i = 0; i < this.nodes.length; i++ ) {
            var node = this.nodes[i];
            if ( node.getProperty( this.name ) !== undefined ) {
                node.setProperty( this.name, this.value );
                //if ( !noformat ) {
                    node.format(gDrawApp.drawView.ctx);
                //}
            }
        }
        this.view.draw();
    },

    undo: function()
    {
        for ( var i = 0; i < this.nodes.length; i++ ) {
            var node = this.nodes[i];
            if ( this.name in node ) {
                node.setProperty( this.name, this.oldValues[i] );
                node.format(gDrawApp.drawView.ctx);
            }
        }
        this.view.draw();
    }
};

/** @constructor */
function PropertyPanel()
{
    this.div = document.createElement("div");
    $(this.div).addClass("PropertyPanel");

    this.records = [];
    this.recordsByName = {};
    this.view = null; // must be set after construction.
    this.nodes = [];

    this.action = null;
}

PropertyPanel.prototype = {
    loadFromNodes: function( nodes )
    {
        this.action = null;
        this.records.length = 0;
        this.recordsByName = {};
        this.nodes = nodes.concat();
        var hasGroup = false;

        // for each node,
        for ( var i = 0; i < nodes.length; i++ ) {
            var node = nodes[i];

            if ( node.isGroupMember() ) {
                hasGroup = true;
            }

            // get the property list.
            var properties = node.getPropertyList();

            // add the property from the node.
            for ( var j = 0; j < properties.length; j++ ) {
                this.loadFromNode( properties[j], node );
            }
        }


        this.createControls();
        var keydiv = $("<div>").addClass("keydiv");
        $(this.div).append( keydiv );

        $(keydiv).append("<h1>Keyboard</h1>");

        var Shortcuts = [
            {
                key: 'C',
                description: "Draw curves"         
            },
            {
                key: 'L',
                description: "Draw lines"         
            }
        ];

        if ( nodes.length > 0 ) {
            Shortcuts.push( 
                {
                    key: 'Del',
                    description: "Delete Selection"         
                },
                {
                    key: 'Ctrl+D',
                    description: "Duplicate Selection"         
                },
                {
                    key: 'PageUp',
                    description: "Move selection closer"         
                },
                {
                    key: 'PageDown',
                    description: "Move selection away"         
                }
            );
        }

        if ( nodes.length > 1 ) {
            Shortcuts.push( 
                {
                    key: 'Ctrl+G',
                    description: "Group selection"         
                });
        }

        if ( hasGroup ) {
            Shortcuts.push( 
                {
                    key: 'Ctrl+Shift+G',
                    description: "Break apart group"         
                }
            );
        }

        for ( i = 0; i < Shortcuts.length; i++ ) {
            var a = $("<a>").text(Shortcuts[i].key).addClass("key");
            var p = $("<p>").append(a);
            p[0].appendChild(document.createTextNode(Shortcuts[i].description));
            $(keydiv).append(p);
        }
    },

    loadFromNode: function( property, node )
    {
        var record;

        // if we already have the property,
        if ( property.name in this.recordsByName ) {
            record = this.recordsByName[property.name];

            // if the node's value differs from the property value,
            if ( record.value !== node.getProperty( property.name ) ) {
                // mark the property as "multiple values"
                record.value = null;
            }
        } else {
            // don't already have the property. Add it.
            record = {
                property: property,
                value: node.getProperty( property.name )
            };
            this.records.push( record );
            this.recordsByName[property.name] = record;
        }
    },

    createControls: function()
    {
        // remove all existing controls.
        $(this.div).empty();

        var i;
        var j;
        var input;
        var self = this;

		var selectOnChangeFn = function() {
			var which = parseInt( this.value, 10 );
			self.apply( this.prop.name, this.prop.values[which].value );
		};

        var onEnterFn = function(e) {
            if ( e.keyCode === 13 ) {
                self.apply( this.prop.name, this.value ); 
            }
        };

        var onWheelClickFn = function() {
            self.wheelClicked( this );   
        };


        // for each property record,
        for ( i = 0; i < this.records.length; i++ ) {
            var record = this.records[i];
            var prop = record.property;
            var div = document.createElement("div");

            // add a span for its name.
            var span = document.createElement("span");
            span.appendChild( document.createTextNode(prop.display) );
            div.appendChild( span );
            div.appendChild( document.createElement("br") );

            // if it's a select, 
            if ( prop.type === "select" ) {
                // create a select box.
                var select = document.createElement("select");

                // for each name/value pair,
                for ( j = 0; j < prop.values.length; j++ ) {
                    var item = prop.values[j];

                    // add the item to the select box.
                    var option = document.createElement("option");
                    option.appendChild( document.createTextNode(item.name) );
                    option.setAttribute( "value", j );

                    // if the value is equal to the value of the record, then
                    // set the item as default.
                    if ( item.value === record.value ) {
                        option.setAttribute( "selected", "" );
                    }

                    select.appendChild( option );
                }

                select.prop = prop;

                select.onchange = selectOnChangeFn;

                div.appendChild( select );
             
            // if it's a color, 
            } else if ( prop.type === "colour" ) {
                // create a text box containing the colour as a string.
                input = document.createElement( "input" );
                input.setAttribute("type", "text");
                input.value = record.value;
                input.prop = prop;

                $(input).keydown( onEnterFn );

                div.appendChild( input );

                var wheel = document.createElement("img");
                wheel.src = "wd-wheel.png";
                wheel.style.verticalAlign = "middle";
                wheel.input = input;
                
                div.appendChild( wheel );

                $(wheel).click( onWheelClickFn );
            // if it's text,    
            } else if ( prop.type === "text" ) {
                // create a text box containing the text.
                input = document.createElement( "input" );
                input.setAttribute("type", "text");
                input.value = record.value;

                input.prop = prop;

                $(input).keydown( onEnterFn );

                div.appendChild( input );

            } else {
                // error! Invalid property type.
                throw "Error: No such property";
            }
            this.div.appendChild( div );
        }
    },

    apply: function( name, value )
    {
        this.view.undoStack.execute( 
            new SetPropertyAction( this.view, this.nodes, name, value )
        );
    },

    wheelClicked: function( element )
    {
        if ( element.hasWheel ) {
            return;
        }

        var wheel = new ColourWheel( 120 );
        var self = this;
        wheel.setFromColour( element.input.value );
        wheel.onUpdate = function( colourStr ) {
            self.colourChanged( colourStr, element.input, element.input.prop );
        };
        element.wheel = wheel;
        element.hasWheel = true;
        element.parentNode.appendChild( wheel.div );
    },

    colourChanged: function( colour, input, prop )
    {
        if ( this.action === null || this.action.name !== prop.name ) {
            this.action = new SetPropertyAction( this.view, this.nodes,
                    prop.name, colour );

            this.view.undoStack.execute( this.action, true );
        }

        this.action.value = colour;
        input.value = colour;
        for ( var i = 0; i < this.nodes.length; i++ ) {
            var node = this.nodes[i];
            node.setProperty( prop.name, colour );
            node.format();
        }

        this.view.draw();
    }

};
