'use strict';
/*@
Ox.Editable <f> Editable element
    () ->              <f> Input Element
    (options) ->       <f> Input Element
    (options, self) -> <f> Input Element
    options <o> Options object
        editing <b|false> If true, loads in editing state
        format <f|null> Format function
            (value) -> <s> Formatted value
            value <s> Input value
    self <o> Shared private variable
@*/
Ox.Editable = function(options, self) {

    self = self || {};
    var that = Ox.Element({
            element: '<div>',
            tooltip: options.tooltip
        }, self)
        .defaults({
            clickLink: null,
            editable: true,
            editing: false,
            format: null,
            height: 0,
            placeholder: '',
            tooltip: '',
            value: '',
            width: 0,
            type: 'input'
        })
        .options(options || {})
        .addClass('OxEditableElement')
        .bind({
            click: function() {
                return false;
            }
        })
        .bindEvent({
            doubleclick: edit,
            singleclick: function(e) {
                if ($(e.target).is('a')) {
                    if (self.options.clickLink) {
                        self.options.clickLink(e);
                    } else {
                        document.location.href = $(e.target).attr('href');
                    }
                }
            }
        });

    self.options.value = self.options.value.toString();

    self.css = {};
    self.$value = Ox.Element(self.options.type == 'input' ? '<span>' : '<div>')
        .addClass('OxValue')
        //.css({background: 'red'})
        .html(formatValue())
        //[self.options.editing ? 'hide' : 'show']()
        .appendTo(that);

    if (self.options.editing) {
        self.options.editing = false;
        edit();
    }

    function cancel() {
        self.options.value = self.originalValue;
        self.$input.value(formatInputValue()).hide();
        self.$test.html(formatTestValue());
        self.$value.html(formatValue()).show();
    }

    function change(event) {
        var height, width;
        self.options.value = event.value;
        self.$value.html(formatValue());
        self.$test.html(formatTestValue());
        //height = self.options.height || Ox.limit(self.$test.height() + 2, self.minHeight, self.maxHeight);
        height = self.options.height || Math.max(self.$test.height() + 2, self.minHeight);
        width = self.options.width || Ox.limit(self.$test.width() + 2, self.minWidth, self.maxWidth);
        Ox.Log('Form', self.options.width, self.$test.width(), 'wxh', width, height)
        if (self.options.type == 'input') {
            self.$input.options({
                width: width
            });
            self.$input.find('input').css({width: width + 'px'});
        } else {
            self.$input.options({
                height: height,
                width: width
            });
            self.$input.find('textarea').css({
                height: height + 'px',
                width: width + 'px'
            });
        }
        /*
        that.triggerEvent('change', {
            value: event.value
        });
        */
    }

    function edit() {
        var height, width;
        if (self.options.editable && !self.options.editing) {
            self.options.editing = true;
            self.originalValue = self.options.value;
            self.minWidth = 8;
            self.maxWidth = that.parent().width();
            self.minHeight = 14;
            self.maxHeight = that.parent().height();
            height = self.options.height || self.$value.height();
            width = self.options.width || self.$value.width();
            self.$value.hide();
            Ox.Log('Form', 'H:::', self.options.height, height)
            if (!self.$test) {
                self.$test = self.$value.$element.clone()
                    .css(Ox.extend({display: 'inline-block'}, self.css))
                    .html(formatTestValue())
                    .hide()
                    .appendTo(that.$element);
                self.$input = Ox.Input({
                        changeOnKeypress: true,
                        style: 'square',
                        type: self.options.type,
                        value: formatInputValue(),
                    })
                    .css(self.css)
                    .bindEvent({
                        blur: submit,
                        cancel: cancel,
                        change: change,
                        submit: submit
                    })
                    .appendTo(that.$element);
                self.$input.find('input').css(self.css);
            }
            self.$input.options({
                    width: width,
                    height: height
                })
                .show();
            if (self.options.type == 'input') {
                self.$input.find('input').css({
                    height: height + 'px',
                    width: width + 'px'
                });
            } else {
                self.$input.find('textarea').css({
                    height: height + 'px',
                    width: width + 'px'
                });
            }
            // fixme: why can't this be chained?
            setTimeout(function() {
                self.$input.focusInput(false);
            }, 0);
            that.$tooltip.options({title: ''});
            that.triggerEvent('edit', {editing: true});
        }
    }

    function formatInputValue() {
        return Ox.decodeHTML(
            self.options.type == 'input'
                ? self.options.value
                : self.options.value.replace(/<br\/?><br\/?>/g, '\n\n')
        );
    }

    function formatTestValue() {
        return self.options.type == 'input'
            ? self.options.value.replace(/ /g, '&nbsp;')
            : Ox.parseHTML(self.options.value || '&nbsp;')
                .replace(/<br\/?>$/, '<br/>&nbsp;');
    }

    function formatValue() {
        var value = self.options.value;
        if (self.options.value === '' && self.options.placeholder) {
            value = self.options.placeholder;
        } else if (self.options.format) {
            value = self.options.format(self.options.value)
        }
        return value;
    }

    function submit() {
        self.options.editing = false;
        self.options.value = Ox.parseHTML(self.$input.value());
        self.$input.value(formatInputValue()).hide();
        self.$test.html(formatTestValue());
        self.$value.html(formatValue()).show();
        that.$tooltip.options({title: self.options.tooltip});
        that.triggerEvent('submit', {
            value: self.options.value
        });
    }

    self.setOption = function(key, value) {
        if (key == 'height' || key == 'width') {
            var css = {};
            css[key] = value + 'px';
            self.$test && self.$test.css(css);
            self.$input && self.$input.css(css);
            self.$input && self.$input.find(self.options.type).css(css);
        }
    };

    that.css = function(css) {
        self.css = css;
        that.$element.css(css);
        self.$value.css(css);
        self.$test && self.$test.css(css);
        self.$input && self.$input.css(css);
        return that;
    };

    return that;

};