Invoice = Class.create();
Invoice.prototype = {
    currency:           'RON',
    currency_products:  'EUR',
    vatRate:            19,
    products:           [],
    rates:              {},

    initialize: function () {
        this.productsContainer = $('invoice-products').up('table');

        $('invoice-series').observe('keyup', (function () {
            this.setSeries($F('invoice-series'));
        }).bind(this));

        $('invoice-number').observe('keyup', (function () {
            this.setNumber($F('invoice-number'));
        }).bind(this));

        new Control.DatePicker('invoice-date', {
            locale: 'ro_RO',
            icon: APP.path.images + 'calendar.png',
            showOnFocus: true,
            onSelect: (function (date) {
                var today = new Date();
                if (date > today) {
                    return;
                }

                this.setDate(date);
            }).bind(this)
        });

        var invoice = this;

        $('invoice-currency-products').observe('change', function (event) {
            invoice.setCurrencyProducts(this.value);
        });

        $('invoice-currency').observe('change', function (event) {
            invoice.setCurrency(this.value);
        });

        $('invoice-vat').observe('change', function (event) {
            invoice.setVAT(this.value);
        });

        $$('.invoice-add-product').invoke('observe', 'click', (function () {
            this.addProduct();
        }).bind(this));

        this.supplier   = new Supplier();
        this.customer   = new Customer();
        this.author     = new Author();
        this.expedition = new Expedition();
    },

    addProduct: function (product) {
        if (!product) {
            product = new Product();
        }

        product.invoice = this;
        product.insert();

        product.setRate(this.rate);
        product.setCrt(this.products.size() + 1);
        product.setCurrency(this.currency_products);
        product.setCurrencyConvert(this.currency);
        product.setVAT(this.vatRate);

        this.products.push(product);
    },

    removeProduct: function (id) {
        var product = this.getProduct(id);

        if (product) {
            product.remove();
            this.products.remove(this.products.indexOf(product));

            this.products.each(function (product, index) {
                product.setCrt(index + 1);
            });
        }
    },

    updatePrice: function () {
        this.price = 0;
        this.vat   = 0;
        this.total = 0;

        this.products.each((function (product) {
            this.price += parseFloat(product.price);
            this.vat   += parseFloat(product.vat);
        }).bind(this));

        this.price = this.round(this.price * this.rate);
        this.vat = this.round(this.vat * this.rate);
        this.total = this.round(this.price + this.vat);


        $('invoice-vat-price').update(this.round(this.price));
        $('invoice-vat-vat').update(this.round(this.vat));
        $('invoice-total').update(this.round(this.total));
    },

    /**
     * Get product by auto-generated id
     */
    getProduct: function (id) {
        return this.products.find(function (product) {
            return product.ids.invoice == id || product.ids.sidebar == id;
        });
    },

    setSeries: function (series) {
        if (!series) {
            series = '...';
        }

        this.series = series;
        $('invoice-series-holder').update(this.series);
    },

    setNumber: function (number) {
        if (!number) {
            number = '...';
        }

        this.number = number;
        $('invoice-number-holder').update(this.number);
    },

    setDate: function (date) {
        this.date        = date;
        this.requestDate = this.formatRequestDate(this.date);

        $('invoice-date-holder').update(this.date ? this.formatDate(this.date) : '...');

        this.convertCurrency();
    },

    setCurrencyProducts: function (currency) {
        this.currency_products = currency;
        this.products.each(function (product) {
            product.setCurrency(currency);
        });

        this.convertCurrency();
    },

    setCurrency: function (currency) {
        this.currency = currency;
        this.products.each(function (product) {
            product.setCurrencyConvert(currency);
        });

        if (this.currency == 'RON') {
            this.enableVAT();
        } else {
            this.setVAT(0);
            this.disableVAT();
        }

        this.productsContainer.select('thead span.currency').invoke('update', this.currency);

        this.convertCurrency();
    },

    setRates: function (rates) {
        for (var day in rates) {
            if (!this.rates[day]) {
                this.rates[day] = rates[day];
            }
        }
    },

    setVAT: function (vat) {
        this.vatRate = parseFloat(vat);

        this.products.each((function (product) {
            product.setVAT(this.vatRate);
        }).bind(this));

        if (this.vatRate) {
            $('invoice-vat-exempt').hide();
            this.productsContainer.down('col.invoice-vat-column').show();
            this.productsContainer.select('.invoice-vat-cell').invoke('show');
            $('invoice-total').colSpan = 2;
            $('invoice-total').previous().removeClassName('last_cell');


        } else {
            $('invoice-vat-exempt').show();
            this.productsContainer.down('col.invoice-vat-column').hide();
            this.productsContainer.select('.invoice-vat-cell').invoke('hide');
            $('invoice-total').colSpan = 1;
            $('invoice-total').previous().addClassName('last_cell');

            this.productsContainer.select('.last').each(function (cell) {
                if (cell.previous()) {
                    cell.previous().addClassName('last');
                }
            });

            this.productsContainer.select('.last_cell').each(function (cell) {
                if (cell.previous()) {
                    cell.previous().addClassName('last_cell');
                }
            });
        }
    },

    enableVAT: function () {
        $('invoice-vat').disabled = false;
    },

    disableVAT: function () {
        $('invoice-vat').disabled = true;
    },

    convertCurrency: function () {
        var rates   = this.getRates();
        this.rate   = rates[this.currency_products] / rates[this.currency];

        this.products.each((function (product) {
            product.setRate(this.rate);
            product.convertCurrency();
        }).bind(this));

        this.updatePrice();

        $('invoice-rate').update("1 " + this.currency_products + ' = ' + this.round(this.rate) + ' ' + this.currency);

        if (this.currency == this.currency_products) {
            $('invoice-convertor').hide();
        } else {
            $('invoice-convertor').show();
        }
    },

    /**
     * Gets current available rates.
     * It goes back a maximum of 5 days to find rates, and requests async if it passes into the previous month
     */
    getRates: function () {
        if (this.rates[this.requestDate]) {
            return this.rates[this.requestDate];
        } else {
            var date = this.date.clone();
            date.setDate(date.getDate() - 5);

            if (date.getMonth() != this.date.getMonth()) {
                this.requestRates(date);
            }

            var i = 1;
            while (!this.rates[this.requestDate] && i < 5) {
                this.date.setDate(this.date.getDate() - 1);
                this.requestDate = this.formatRequestDate(this.date);
                i++;
            }

            return this.rates[this.requestDate];
        }
    },

    /**
     * Request rates for one month from convertor.ro
     */
    requestRates: function (date) {
        var invoice = this;

        new Ajax.Request(APP.path.root + 'rates', {
            parameters: {
                date: this.formatRequestDate(date)
            },
            onSuccess: function (transport) {
                var response = transport.responseText.evalJSON();
                if (!response.type || response.type == 'error') {
                    invoice.setRates(response.rates);
                }
            }
        });
    },

    checkValid: function () {
        var messages = [];

        if (!this.series) {
            messages.push('Nu ati completat seria facturii');
        }

        if (!this.number) {
            messages.push('Nu ati completat numarul facturii');
        }

        if (!this.date) {
            messages.push('Nu ati selectat data facturii');
        }

        if (!this.products.find(function (product) { return product.isValid(); })) {
            messages.push('Nu ati introdus cel putin un produs valid');
        }

        if (!this.supplier.isValid()) {
            messages.push('Nu ati completat toate datele Furnizorului');
        }

        if (!this.customer.isValid()) {
            messages.push('Nu ati completat toate datele Clientului');
        }

        if (!this.author.isValid()) {
            messages.push('Nu ati completat toate datele Intocmitorului');
        }

        return messages;
    },

    round: function (number) {
        return Math.round(number * 100) / 100;
    },

    /**
     * dd/mm/YY
     */
    formatDate: function (date) {
        return (new String(date.getDate())).pad(2, "0", "left") + "/" + (new String(date.getMonth() + 1)).pad(2, "0", "left") + "/" + date.getFullYear();
    },

    /**
     * YYYY-mm-dd
     */
    formatRequestDate: function (date) {
        return date.getFullYear() + "-" + (new String(date.getMonth() + 1)).pad(2, "0", "left") + "-" + (new String(date.getDate() + 1)).pad(2, "0", "left");
    }
};