function KHistory(options={}) {
    $.extend(this, KHistory.default_options, options);

    this.$container = $(this.container);

    this.reset = function() {
        this.$container.html('');
    };

    this.addOpeGroup = function(opegroup) {
        var $day = this._getOrCreateDay(opegroup['at']);
        var $opegroup = this._opeGroupHtml(opegroup);

        $day.after($opegroup);

        var trigramme = opegroup['on_acc_trigramme'];
        var is_cof    = opegroup['is_cof'];
        for (var i=0; i<opegroup['opes'].length; i++) {
            var $ope = this._opeHtml(opegroup['opes'][i], is_cof, trigramme);
            $ope.data('opegroup', opegroup['id']);
            $opegroup.after($ope);
        }
    }

    this._opeHtml = function(ope, is_cof, trigramme) {
        var $ope_html = $(this.template_ope);
        var parsed_amount = parseFloat(ope['amount']);
        var amount = amountDisplay(parsed_amount, is_cof, trigramme);
        var infos1 = '', infos2 = '';

        if (ope['type'] == 'purchase') {
            infos1 = ope['article_nb'];
            infos2 = ope['article__name'];
        } else {
            infos1 = parsed_amount.toFixed(2)+'€';
            switch (ope['type']) {
                case 'initial':
                    infos2 = 'Initial';
                    break;
                case 'withdraw':
                    infos2 = 'Retrait';
                    break;
                case 'deposit':
                    infos2 = 'Charge';
                    break;
                case 'edit':
                    infos2 = 'Édition';
                    break;
            }
        }

        $ope_html
            .data('ope', ope['id'])
            .find('.amount').text(amount).end()
            .find('.infos1').text(infos1).end()
            .find('.infos2').text(infos2).end();

        var addcost_for = ope['addcost_for__trigramme'];
        if (addcost_for) {
            var addcost_amount = parseFloat(ope['addcost_amount']);
            $ope_html.find('.addcost').text('('+amountDisplay(addcost_amount, is_cof)+'UKF pour '+addcost_for+')');
        }

        if (ope['canceled_at'])
            this.cancelOpe(ope, $ope_html);

        return $ope_html;
    }

    this.cancelOpe = function(ope, $ope = null) {
        if (!$ope)
            $ope = this.findOpe(ope['id']);

        var cancel = 'Annulé';
        var canceled_at = dateUTCToParis(ope['canceled_at']);
        if (ope['canceled_by__trigramme'])
            cancel += ' par '+ope['canceled_by__trigramme'];
        cancel += ' le '+canceled_at.format('DD/MM/YY à HH:mm:ss');

        $ope.addClass('canceled').find('.canceled').text(cancel);
    }

    this._opeGroupHtml = function(opegroup) {
        var $opegroup_html = $(this.template_opegroup);

        var at        = dateUTCToParis(opegroup['at']).format('HH:mm:ss');
        var trigramme = opegroup['on_acc__trigramme'];
        var amount    = amountDisplay(
                parseFloat(opegroup['amount']), opegroup['is_cof'], trigramme);
        var comment = opegroup['comment'] || '';

        $opegroup_html
            .data('opegroup', opegroup['id'])
            .find('.time').text(at).end()
            .find('.amount').text(amount).end()
            .find('.comment').text(comment).end()
            .find('.trigramme').text(trigramme).end();

        if (!this.display_trigramme)
            $opegroup_html.find('.trigramme').remove();

        if (opegroup['valid_by__trigramme'])
            $opegroup_html.find('.valid_by').text('Par '+opegroup['valid_by__trigramme']);

        return $opegroup_html;
    }

    this._getOrCreateDay = function(date) {
        var at = dateUTCToParis(date);
        var at_ser = at.format('YYYY-MM-DD');
        var $day = this.$container.find('.day').filter(function() {
            return $(this).data('date') == at_ser
        });
        if ($day.length == 1)
            return $day;
        var $day = $(this.template_day).prependTo(this.$container);
        return $day.data('date', at_ser).text(at.format('D MMMM'));
    }

    this.findOpeGroup = function(id) {
        return this.$container.find('.opegroup').filter(function() {
            return $(this).data('opegroup') == id
        });
    }

    this.findOpe = function(id) {
        return this.$container.find('.ope').filter(function() {
            return $(this).data('ope') == id
        });
    }

    this.cancelOpeGroup = function(opegroup) {
        var $opegroup = this.findOpeGroup(opegroup['id']);
        var trigramme = $opegroup.find('.trigramme').text();
        var amount = amountDisplay(
                parseFloat(opegroup['amount'], opegroup['is_cof'], trigramme));
        $opegroup.find('.amount').text(amount);
    }

}

KHistory.default_options = {
    container: '#history',
    template_day: '<div class="day"></div>',
    template_opegroup: '<div class="opegroup"><span class="time"></span><span class="trigramme"></span><span class="amount"></span><span class="valid_by"></span><span class="comment"></span></div>',
    template_ope: '<div class="ope"><span class="amount"></span><span class="infos1"></span><span class="infos2"></span><span class="addcost"></span><span class="canceled"></span></div>',
    display_trigramme: true,
}
