/**
 * @category   Aims
 * @package    Aims_Quoteimproved
 * @author     AIMS Interactive
 * @license    http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
 */

//var Carts = Class.create();
//Carts.prototype = {
//    
//    initialize: function(config) {
//        
//        var carts = $H(config);
//        carts.each(function(cart) {
//            id = cart.key;
//            cart = new Cart(cart.value);
//            this.addCart(id, cart);
//        }.bind(this));
//        
//    },
//    
//    addCart: function(id, cart) {
//        this.carts.set(id, cart);
//    },
//    
//    getCart: function(id) {
//        return this.carts.get(id);
//    },
//    
//    deleteCart: function(id) {
//        
//    }
//    
//}

var Cart = Class.create();
Cart.prototype = {
    
    initialize: function(config) {
        
        this.cart = config.cart;
        this.webreference = config.webreference;
        this.create = config.create;
        this.remove = config.remove;
        this.reload_areas = config.reload_areas;
        this.default_url = config.default_url;
        this.template = new Template('<input type="hidden" value="1" name="cart_area[#{area}]">');
        this.items = new Hash();
        this.dev = config.dev;
        
        if(config.comment) {
            this.comment = {data: config.comment.data.evalJSON(), template: config.comment.template.evalJSON()};
        }

        if(config.items && config.items.length > 0) {
            var length = config.items.length;
            for(var i=0;i<length;i++) {
                var item = new Cart_Item(config.items[i].evalJSON());
                this.addItem(item);
            }
            
            this.getFirstItem().arrow_move_up.hide();
            this.getLastItem().arrow_move_down.hide();
            
        }

        this.processEvents();
        
    },
    
    processEvents: function() {
        
        if(this.cart && $(this.cart.input)) {
            $(this.cart.input).observe('change', function() {
                this.reloadArea(this.cart.area, this.cart.url);
            }.bind(this));
        }

        if(this.webreference && $(this.webreference.input)) {
            $(this.webreference.input).observe('blur', function() {
                this.changeWebReference($(this.webreference.input).value);
            }.bind(this));
        }
        
        if(this.create && $(this.create.input)) {
            $(this.create.input).observe('click', function() {
                this.createQuote($(this.create.input+'_value').value);
            }.bind(this));
        }

        if(this.remove && $(this.remove.input)) {
            $(this.remove.input).observe('click', function() {
                this.reloadArea(this.remove.area, this.remove.url);
            }.bind(this));
        }
        
    },

    changeWebReference: function(webreference) {
        
        if(webreference != '' && webreference != this.webreference.value) {
            this.reloadArea(this.webreference.area, this.webreference.url);
        }

    },

    createQuote: function() {
        this.reloadArea(this.create.area, this.create.url);
    },

    addItem: function(item) {
        item.cart = this;
        this.getItems().set(item.id, item);
    },
    
    getItem: function(id) {
        return this.getItems().get(id);
    },

    getItems: function() {
        return this.items;
    },
    
    countItems: function() {
        return this.getItems().keys().length;
    },
    
    getFirstItem: function() {
        
        var item;
        var items = this.getItems().values().sort(this.sortItems);
        if(items.length > 0) {
            item = items.first();
        }
        
        return item;
    },

    getLastItem: function() {
        
        var item;
        var items = this.getItems().values().sort(this.asortItems);
        
        if(items.length > 0) {
            item = items.first();
        }
        
        return item;
        
    },
    
    sortItems: function(a, b) {
        return a.position - b.position;
    },
    
    asortItems: function(a, b) {
        return b.position - a.position;
    },
    
    calcItemsPosition: function(item, position) {
     
        this.getItems().each(function(current_item) {
            current_item = current_item.value;
            if(current_item.id != item.id && current_item.position == item.position) {
                current_item.setPosition(position);
                
                if(position > item.position) {
                    current_item.row.insert({before: item.row});
                }
                else {
                    var comment = current_item.getLastComment();
                    if(comment) comment.row.insert({after: item.row});
                    else current_item.row.insert({after: item.row});
                }
                item.moveComments();
                item.save();
                new Effect.Pulsate(item.row, {pulses: 1, duration:0.3, beforeStart:function(){this.decorate()}.bind(this)});
            }
        }.bind(this));
        
    },
    
    checkItemsArrows: function() {
        
        this.getItems().each(function(item) {
            item.value.checkArrows();
        });
        
    },

    reloadArea: function(area, url) {
        area = $(area);
        if(url == 'undefined') url = this.default_url;
        var i = 0;
        for(i=0;i<this.reload_areas.length;i++) {
            if(this.reload_areas[i] != '' && this.reload_areas[i] != null) {
                area.insert(this.template.evaluate({area: this.reload_areas[i]}));
            }
        }
        submitAndReloadArea(area, url, true);
        
    },
    
    decorate: function() {
        
        this.getItems().each(function(item) {
            item = item.value;
            item.row.removeClassName('even').removeClassName('odd');
            if(item.hasComments()) {
                item.comments.each(function(comment) {
                    comment = comment.value;
                    comment.row.removeClassName('even').removeClassName('odd');
                });
            }
        });
        
        decorateGeneric($('shopping-cart-table').select('tbody tr'), ['odd', 'even', 'first', 'last']);
    },
    
    canUseAjax: function() {
        return this.reload_areas.indexOf('content') != -1;
    }
    
}

var Cart_Item = Class.create();
Cart_Item.prototype = {

    initialize: function(config) {

        this.id = config.id;
        this.position = config.position;
        this.arrow_move_down = $('down_'+this.id);
        this.arrow_move_up = $('up_'+this.id);
        this.qty = config.qty;
        this.row = $('item_' + this.id);
        this.url = config.url;
        this.hasNewComment = false;
        this.comments = new Hash();
        this.reloader = new Ajax_Loader({area: this.row});   

        var length = config.comments.length;
        
        if(length > 0) {
            for(var i=0;i<length;i++) {
                var comment = new Comment(config.comments[i].evalJSON());
                this.addComment(comment);
            }

            this.getFirstComment().arrow_move_up.hide();
            this.getLastComment().arrow_move_down.hide();
        }
        
        this.processEvents();

    },
    
    processEvents: function() {
        
        $('delete_' + this.id).observe('click', this.remove.bind(this));
        $('qty_' + this.id).observe('blur', this.changeQty.bind(this));

        $('add_comment_' + this.id).observe('click', function() {
            if(this.canCreateComment()) {
                this.createComment();
            }
            else {
                this.getNewComment().pulseButton();
            }
        }.bind(this));
        
        this.arrow_move_up.observe('click', this.moveUp.bind(this));
        this.arrow_move_down.observe('click', this.moveDown.bind(this));
        
        this.reloader.addCallback('success', this.afterSave.bind(this));
        
    },

    changeQty: function(e) {

        var qty = e.element().value;
        
        this.qty = qty;
        this.save();
        
        return this;

    },

    createComment: function() {

        var position = this.getNextPosition();
        var id = 'no_id_'+Math.round(Math.random()*10000);
        
        var content = new Template(this.cart.comment.template).evaluate({position: position, id: id});
        this.getLastCommentElement().insert({after: content});
        var tr = $('comment_template');
        tr.writeAttribute('id', 'comment_' + id);
        
        var config = Object.clone(this.cart.comment.data);
        config.id = id;
        config.input = config.input.replace('#{id}', id);
        config.position = position;
        
        var comment = new Comment(config);
        this.addComment(comment);
        this.hasNewComment = true;
        Effect.Appear(tr, {duration: 0.5, 
            beforeFinish: function() {
                var offset = this.calcOffset();                
                Effect.ScrollTo($(config.input), {offset: offset});
            }.bind(this),
            afterFinish: function() {
                $(config.input).focus();
                comment.validate_button.show();
                
            }.bind(this)
        });
        
        return this;
        
    },

    addComment: function(comment) {
                
        comment.item = this;
        this.comments.set(comment.position, comment);
        this.setCommentsPosition();
        this.checkCommentsArrows();
        
    },
    
    getComment: function(id) {
        
        var comment;
        this.comments.each(function(current_comment) {
            if(current_comment.value.row.id == id) comment = current_comment.value;
        });
        
        return comment;
    },

    removeComment: function(id) {
        
        var comment = this.comments.get(id);
        
        if(comment) {
            if(this.comments.get(id).isNewObject) {
                this.hasNewComment = false;
            }
            this.comments.unset(id);
        }
        
        return this;
        
    },
    
    calcCommentsPosition: function(comment, position) {
                
        this.comments.each(function(current_comment) {
            current_comment = current_comment.value;
            if(current_comment.id != comment.id && current_comment.position == comment.position) {
                
                current_comment.setPosition(position);
                if(position > comment.position) current_comment.row.insert({before: comment.row});
                else current_comment.row.insert({after: comment.row});
                new Effect.Pulsate(comment.input, {pulses: 2, duration:0.5});
                
                this.toggleCommentsPosition(comment, current_comment);
                
            }
        }.bind(this));
        
        this.cart.decorate();
    },
    
    setCommentsPosition: function() {
        
        var position = 1;
        var comments = new Hash();
        var keys = this.comments.keys().sort();
        
        for(var i=0;i<keys.length;i++) {
            var comment = this.comments.get(keys[i]);
            comment.original_position = position;
            comment.setPosition(position);
            comments.set(position, comment);
            position++;
        }
        
        this.comments = comments;

        return this;
    },
    
    toggleCommentsPosition: function(p1, p2) {
        this.comments.set(p1.position, p1);
        this.comments.set(p2.position, p2);
    },
    
    moveComments: function() {
        
        var last;
        
        this.comments.each(function(comment) {
            comment = comment.value;
        
            if(!last) this.row.insert({after: comment.row});
            else last.row.insert({after: comment.row});
            last = comment;
        }.bind(this));
        
        return this;
        
    },
    
    hasComments: function() {
        return this.getFirstComment() ? true : false;
    },
    
    getFirstComment: function() {
        
        var comment;
        var comments = this.comments.values().sort(this.sortComments);
        if(comments.length > 0) {
            comment = comments.first();
        }
        
        return comment;
    },

    getLastComment: function() {
        
        var comment;
        var comments = this.comments.values().sort(this.asortComments);
        if(comments.length > 0) {
            comment = comments.first();
        }
        
        return comment;
        
    },
    
    getNewComment: function() {
        
        var comment;
        this.comments.each(function(current_comment) {
            current_comment = current_comment.value;
            if(current_comment.isNewObject) {
                comment = current_comment;
            }
        });
        
        return comment;
    },

    getLastCommentElement: function() {
        
        var comment = this.getLastComment();
        
        if(comment) return $('comment_' + comment.id);
        else return this.row;
    },
        
    sortComments: function(a, b) {
        return a.position - b.position;
    },
    
    asortComments: function(a, b) {
        return b.position - a.position;
    },

    getNextPosition: function() {
        
        var position = 1;
        var comment = this.getLastComment();
        if(comment) position = comment.getPosition() + 1;
        
        return position;
    },
    
    getCommentMaxPosition: function() {
        
        var position = 0;
        this.comments.each(function(current_comment) {
            current_comment = current_comment.value;
            if(!current_comment.isNewObject) {
                position++;
            }
        });
        
        return position;
    },
    
    moveUp: function(e) {
        
        if(!this.canMoveUp()) return;
        var position = this.getPosition();
        this.setPosition(this.getPosition()-1);
        this.cart.calcItemsPosition(this, position);
        
        this.checkAllArrows();
        
    },

    moveDown: function(e) {
        
        if(!this.canMoveDown()) return;
        var position = this.getPosition();
        this.setPosition(this.getPosition()+1);
        this.cart.calcItemsPosition(this, position);
        
        this.checkAllArrows();
        
    },
    
    checkArrows: function() {
        
        if(!this.canMoveUp()) this.arrow_move_up.hide();
        else this.arrow_move_up.show();
        
        if(this.canMoveDown()) this.arrow_move_down.show();
        else this.arrow_move_down.hide();
        
    },
    
    checkAllArrows: function() {
        this.cart.checkItemsArrows();
        return this;
    },
    
    checkCommentsStates: function() {
        
        this.comments.each(function(current_comment) {
            current_comment.value.checkState();
        });
        
    },
        
    checkCommentsArrows: function() {
        
        this.comments.each(function(current_comment) {
            current_comment.value.checkArrows();
        });
        
    },
        
    getPosition: function() {
        return parseInt(this.position);
    },
    
    setPosition: function(position) {
        this.position = position;
        this.arrow_move_up.previous('input').value = position;
    },
    
    canMoveUp: function() {
        return this.position > 1;
    },
    
    canMoveDown: function() {
        return this.position < this.getMaxPosition();        
    },
    
    getMaxPosition: function() {
        return this.cart.countItems();
    },
    
    canCreateComment: function() {
        return !this.hasNewComment;
    },
    
    calcOffset: function() {
        
        var offset = 0;
        var max_height = screen.availHeight - 200;
        
        this.comments.each(function(current_comment) {
            
            current_comment = current_comment.value;
            var row_height = current_comment.row.getHeight();
            if(!current_comment.isNewObject) {// && ((offset + row_height*2) < max_height)) {
                offset += row_height;
            }
            
        }.bind(this));
        
        var row_height = this.row.getHeight();
        if((offset + row_height*2) < max_height) {
            offset += row_height + 20;
        }
        
        return offset+row_height > max_height ? 20*-1 : offset*-1;

    },
    
    save: function() {
        
        if(this.qty == 0) this.remove();
        else this.reload();
        
        return this;
        
    },
    
    remove: function() {

        this.comments.each(function(comment) {
            comment.value.remove();
        }.bind(this));
        
        this.reload();
        
        return this;
        
    },

    reload: function() {
        
        this.reloader
            .setUrl(new Template(this.url).evaluate({position: this.position}))
            .submit()
        ;
        
        return this;
//        this.cart.reloadArea(this.cart.cart.area, this.url);
    },
    
    afterSave:function() {
        
    }

}

var Comment = Class.create();
Comment.prototype = {

    initialize: function(config){

        this.id = config.id;
        this.isNewObject = this.id.indexOf('no_id') === 0;
        this.hasChanged = false;
        this.position = config.position;
        this.original_position = config.position;
        this.url = config.url;
        this.input = $(config.input);
        this.input_value = this.input.getValue();
        this.arrow_move_down = $('down_'+this.id);
        this.arrow_move_up = $('up_'+this.id);
        this.validate_button = $('validate_'+this.id);
        this.row = $('comment_' + this.id);
        this.reloader = new Ajax_Loader({area: this.row});        
        
        this.processEvents();
    },

    processEvents: function() {

        this.input.observe('click', function() {
            if(!this.validate_button.visible()) this.validate_button.show();
        }.bind(this)).observe('blur', function() {
            if(this.isNewObject && isEmpty(this.input.getValue())) this.remove();
//            else if(this.canHideButton()) this.validate_button.hide();
            else this.pulseButton();
            this.hasChanged = true;
            this.checkState();
        }.bind(this));
        
        this.arrow_move_up.observe('click', this.moveUp.bind(this));
        this.arrow_move_down.observe('click', this.moveDown.bind(this));
        
        this.validate_button.observe('click', function() {
            if(this.input.getValue() == '') this.remove();
            else if(!this.canHideButton()) this.save();
        }.bind(this));

        $('remove_'+this.id).observe('click', function() {
            this.remove();
        }.bind(this));
        
        this.reloader
            .addCallback('success', this.decorate)
            .addCallback('error', this.errorReload)
            .setObject(this)
        ;
        
//        this.draggable = new Draggable(this.row,{
//            revert:true, 
//            ghosting:true, 
//            constraint:'vertical'
//        });
//        Droppables.add(this.row, {
//            accept: 'comment',
//            onDrop: this.drop.bind(this)
//        });
        
    },

    moveUp: function(e) {
        
        this.hasChanged = true;
        
        if(!this.canMoveUp()) return;
        var position = this.getPosition();
        this.setPosition(this.getPosition()-1);
        this.item.calcCommentsPosition(this, position);
        
        this.checkAll();
//        this.checkAllStates();
//        this.checkAllArrows();
//        this.checkState();

    },

    moveDown: function(e) {
        
        this.hasChanged = true;
        
        if(!this.canMoveDown()) return;
        var position = this.getPosition();
        this.setPosition(this.getPosition()+1);
        this.item.calcCommentsPosition(this, position);
        
        
        this.checkAll();
//        this.checkAllStates();
//        this.checkAllArrows();
//        this.checkState();
        
    },
    
    drop: function(dragged, dropped, event) {
        
        var comment = this.item.getComment(dragged.id);
        
        if(comment) {
            
            this.hasChanged = true;
            
            var position = comment.position;
            comment.setPosition(this.position);

            comment.item.calcCommentsPosition(comment, position);


            comment.checkAll();
//            comment.checkAllStates();
//            comment.checkAllArrows();
//            comment.checkState();
        }
        
    },
    
    save: function() {
        
        this.item.removeComment(this.position);
        this.reloader.addCallback('success', this.decorate);
        this.reloadArea();
        this.validate_button.hide();
        
        return this;
        
    },

    remove: function() {
        
        if(this.row) Effect.Fade(this.row, {
            duration: 0.5, 
            afterFinish: function() {
                if(!this.isNewObject) {
                    this.input.value = '';
                    this.reloader.addCallback('success', this.removeRow);
                    this.reloadArea();
                }
                else {
                    this.removeRow();
                }
            }.bind(this)
        });
        
        return this;

    },
    
    decorate: function() {
        this.item.cart.decorate();
    },
    
    removeRow: function() {
        
        this.item.removeComment(this.position);
        this.row.remove();
        this.item.setCommentsPosition()
            .checkCommentsArrows();
        
        this.decorate();
        
    },
    
    errorReload: function() {
        this.row.show();
        alert('fire error OK');
        this.validate_button.show();
    },
    
    reloadArea: function() {
        this.reloader
            .setUrl(new Template(this.url).evaluate({id:this.id, item_id: this.item.id, position:this.position}))
            .submit()
        ;
    },
    
    checkState: function() {
        
        if(this.canHideButton()) {
            this.row.setStyle({backgroundColor: null});
            this.validate_button.hide();
            this.hasChanged = false;
        }
        else {
            if(this.hasChanged) {
                this.row.setStyle({backgroundColor: '#FFDFC6'});
                this.validate_button.show();
            }
        }

    },
        
    checkAllStates: function() {
        this.item.checkCommentsStates();
        return this;
    },
    
    checkArrows: function() {

        if(this.canMoveUp()) this.arrow_move_up.show();
        else this.arrow_move_up.hide();
        
        if(this.canMoveDown()) this.arrow_move_down.show();
        else this.arrow_move_down.hide();

        return this;
    },
        
    checkAllArrows: function() {
        this.item.checkCommentsArrows();
        return this;
    },
    
    checkAll: function() {
        this.checkAllStates();
        this.checkAllArrows();
        return this;
    },
    
    canMoveUp: function() {
        return !this.isNewObject && this.position > 1;
    },
    
    canMoveDown: function() {
        return !this.isNewObject && this.position < this.getMaxPosition();        
    },
    
    getMaxPosition: function() {
        return this.item.getCommentMaxPosition();
    },
    
    getPosition: function() {
        return parseInt(this.position);
    },
    
    setPosition: function(position) {
        this.position = position;
        this.arrow_move_up.previous().value = position;
    },
    
    canHideButton: function() {
        return this.input.getValue() == this.input_value && this.position == this.original_position;
    },
    
    pulseButton: function() {
        new Effect.Pulsate(this.validate_button, {pulses:2, duration:0.5, afterFinish: function(){this.validate_button.setOpacity(1)}.bind(this)});
//        new Effect.Shake(this.validate_button, {duration:0.5, distance:10});
    }

}

Ajax_Loader = new Class.create();
Ajax_Loader.prototype = {
    
    initialize: function(config) {
        
        this.area = $(config.area);
        this.showloader = true;
        this.callbacks = new Hash();
        this.object = null;
        this.loader = null;
        this.url = '';
        
    },
    
    addCallback: function(name, callback) {
        this.callbacks.set(name, callback);
        return this;
    },
    
    setObject: function(object) {
        this.object = object;
        return this;
    },
    
    setUrl: function(url) {
        this.url = url;
        return this;
    },
    
    submit: function() {
       
        if(this.area) {
            
            var fields = this.area.select('input', 'select', 'textarea');
            var data = Form.serializeElements(fields, true);
            var url = this.url + (this.url.match(new RegExp('\\?')) ? '&isAjax=true' : '?isAjax=true');
            
            if(this.showloader == true) {
                if(!this.loader) this.loader = $('loading-mask');
                this.loader.show();
            }
            
            new Ajax.Request(url, {
                parameters: $H(data),
                loaderArea: this.area,
                onSuccess: function(transport) {
                    
                    var error = false;
                    try {
                        
                        if (transport.responseText.isJSON()) {
                            var response = transport.responseText.evalJSON()
                            if (response.error) {
                                alert(response.message);
                                error = true;
                            }
                            if(response.ajaxExpired && response.ajaxRedirect) {
                                setLocation(response.ajaxRedirect);
                            }

                            if(response.blocks) {

                                if(response.blocks.length > 0) {

                                    for(var i=0;i<response.blocks.length;i++) {

                                        var block = response.blocks[i];
                                        if(!block.id) block.id = this.area;

                                        if(block.value.length > 0) {
                                            this.update(block.id,block.value, block.useEffect);
                                        }

                                    }

                                }
                                else {

                                    block = response.blocks;
                                    if(!block.id) block.id = this.area;

                                    if(response.blocks.value.length > 0) {
                                        this.update(response.blocks.id,response.blocks.value, response.blocks.useEffect);
                                    }
                                }

                            }
                        } else {
                            if(transport.responseText != '') {
                                this.update(this.area, transport.responseText, true);
                            }
                        }
                        
                    }
                    catch (e) {
                        this.update(this.area, transport.responseText, true);
                    }
                    
                    if(error) {
                        if(this.callbacks.get('error')) {
                            this.callbacks.get('error').call(this.object);
                        }
                    }
                    else if(this.callbacks.get('success')) {
                        this.callbacks.get('success').call(this.object);
                    }
                    
                    if(this.showloader == true) {
                        this.loader.hide();
                    }

                }.bind(this),
                onFailure: function() {
                    if(this.callbacks.get('error')) {
                        this.callbacks.get('error').call(this.object);
                    }

                    if(this.showloader == true) {
                        this.loader.hide();
                    }
                }
            });

        }

    },

    update: function(id, value, useEffect) {

        if(useEffect) {
            Effect.Fade(id, {
                duration:0.5,
                fps:25,
                afterFinish:function() {
                    Element.replace(id, value);
                    $(id).show();
                }
            });
        }
        else {
            Element.replace(id, value);
        }
    }
    
}
