$().ready(function() {
    
    $('#columns_colorpicker').farbtastic(function(color) {
        field = $('#id_columns_color');
        $(field).css({backgroundColor: color});
        $(field).val(color);
        $(field).trigger('change');
    });
    $('#baseline_colorpicker').farbtastic(function(color) {
        field = $('#id_baseline_color');
        $(field).css({backgroundColor: color});
        $(field).val(color);
        $(field).trigger('change');
    });
    
    $('#columns_opacity_slider').slider({
        min:0, max: 1, step: 0.01, value: 1, orientation: 'vertical',
        slide: function(e, ui) {
            $('#columns_colorpicker .farbtastic').css('opacity', ui.value);
            $('#id_columns_opacity').val(ui.value);
            return true;
        },
    });
    $('#baseline_opacity_slider').slider({
        min:0, max: 1, step: 0.01, value: 1, orientation: 'vertical',
        slide: function(e, ui) {
            $('#baseline_colorpicker .farbtastic').css('opacity', ui.value);
            $('#id_baseline_opacity').val(ui.value);
            return true;
        },
    });
    $('#options_colors').toggle(function(e) {
        // open
        e.preventDefault();
        $('.ui-icon',this).removeClass('ui-icon-triangle-1-e');
        $('.ui-icon',this).addClass('ui-icon-triangle-1-s');
        $('#colors').slideDown();
    }, function(e) {
        // close
        e.preventDefault();
        $('.ui-icon',this).removeClass('ui-icon-triangle-1-s');
        $('.ui-icon',this).addClass('ui-icon-triangle-1-e');
        $('#colors').slideUp();
    });
        
    var SYSTEMS = {
        'metric': 'mm',
        'imperial': 'in',
        'pixels': 'px'
    }
    var UNITS = {
        'px': 1.0,
        'pt': 1.0,
        'in': 72.0,
        'mm': 0.0393700787*72
    }
    var PAPER_SIZE = { // in mm
        'A5': [148*UNITS['mm'],210*UNITS['mm']],
        'A4': [210*UNITS['mm'],297*UNITS['mm']],
        'A3': [297*UNITS['mm'],420*UNITS['mm']],
        'LETTER': [216*UNITS['mm'],279*UNITS['mm']], //according to wikipedia
        'TABLOID': [432*UNITS['mm'],279*UNITS['mm']] //according to wikipedia
    }
    var MAX_CANVAS_WIDTH = 658;
    var ZOOMS = [25,50,75,100];
    
    var CANVAS_DIV = $('#canvas');
    
    function parse_unit(value, unit) {
        return value*UNITS[unit];
    }
    function convert_to_unit(value, unit) {
        return value/UNITS[unit];
    }
    function get_size(e_value,e_unit) {
        val = e_value.val();
        unit = e_unit.val();
        return parse_unit(val, unit);
    }
    
    var e_form = $('#gridder');
    var e_width = $('#id_width');
    var e_width_unit = $('#id_width_unit');
    var e_height = $('#id_height');
    var e_height_unit = $('#id_height_unit');
    var e_columns = $('#id_columns');
    var e_columns_gutter = $('#id_columns_gutter');
    var e_columns_gutter_unit = $('#id_columns_gutter_unit');
    var e_columns_width = $('#id_cols_width');
    var e_columns_unit = $('#id_cols_width_unit');

    var e_baseline = $('#id_baseline');
    var e_baseline_unit = $('#id_baseline_unit');
    
    var e_margin_left = $('#id_margin_left');
    var e_margin_left_unit = $('#id_margin_left_unit');
    var e_margin_right = $('#id_margin_right');
    var e_margin_right_unit = $('#id_margin_right_unit');
    var e_margin_top = $('#id_margin_top');
    var e_margin_top_unit = $('#id_margin_top_unit');
    var e_margin_bottom = $('#id_margin_bottom');
    var e_margin_bottom_unit = $('#id_margin_bottom_unit');
    
    var e_cols_width_unit = $('#id_cols_width_unit');

    var e_cols_color = $('#id_columns_color');
    var e_baseline_color = $('#id_baseline_color');

    /* shortcuts */
    var e_values_units = [
        [e_width,e_width_unit],
        [e_height,e_height_unit],
        [e_columns_width,e_columns_unit],
        [e_columns_gutter,e_columns_gutter_unit],
        [e_baseline,e_baseline_unit],
        [e_margin_left,e_margin_left_unit],
        [e_margin_right,e_margin_right_unit],
        [e_margin_top,e_margin_top_unit],
        [e_margin_bottom,e_margin_bottom_unit]
    ];
    
    function convert() {
        e_val = $(this).prev();
        val = (e_val.val()*UNITS[$(this).data('old')])/UNITS[$(this).val()];
        $(this).data('old',$(this).val());
        e_val.val(val);
        calculate_columns_width();
    }

    $('#units input').click(function(e) {
        e.preventDefault();
        var unit = SYSTEMS[$(this).val()];
        $(e_values_units).each(function() {
            e_val = this[0];
            e_unit = this[1];
            
            val = ($(e_val).val()*UNITS[$(e_unit).val()])/UNITS[unit];
            $(e_val).val(val);
            $(e_unit).val(unit);
        });
        $('select', e_form).unbind('change');
        calculate_columns_width();
        calculate_gutter_width();
        $('select', e_form).change(convert);
    });
    
    /* increase/decrease */
    $(e_columns).increase_widget({min: 1});
    
    $('input', e_form).keyup(function() { $(this).trigger('change'); });
    $('input', e_form).blur(function() { $(this).trigger('change'); });
    $('input', e_form).change(function() {
        calculate_columns_width();
        draw();
    });
    $('select', e_form).change(convert);
    $('select', e_form).focus(function(e) {
        $(this).data('old',$(this).val());
    });
    e_columns_width.unbind('change');
    e_columns_width.change(function() {
        calculate_gutter_width();
        draw();
    });
    
    $('#paper_size').unbind('change');
    $('#paper_size').change(function(){
        w = PAPER_SIZE[$(this).val()][0];
        h = PAPER_SIZE[$(this).val()][1];
        converted_w = w/UNITS[e_width_unit.val()];
        converted_h = h/UNITS[e_height_unit.val()];
        e_width.val(converted_w.toFixed(1));
        e_height.val(converted_h.toFixed(1));
        refresh();
    });

    function gather_info() {
        page = {
            'width': get_size(e_width, e_width_unit),
            'height': get_size(e_height,e_height_unit),
            'margin_top': get_size(e_margin_top,e_margin_top_unit),
            'margin_bottom': get_size(e_margin_bottom,e_margin_bottom_unit),
            'margin_left': get_size(e_margin_left,e_margin_left_unit),
            'margin_right': get_size(e_margin_right,e_margin_right_unit)
        };
        columns = {
            'count': e_columns.val(),
            'width': get_size(e_columns_width, e_cols_width_unit),
            'width_unit': e_cols_width_unit.val(),
            'gutter': get_size(e_columns_gutter,e_columns_gutter_unit),
            'gutter_unit': e_columns_gutter_unit.val(),
            'color': e_cols_color.val()
        };
        
        baseline = {
            'size': get_size(e_baseline,e_baseline_unit),
            'color': e_baseline_color.val()
        };
        ratio = MAX_CANVAS_WIDTH/page['width'];
        return {
            'page': page,
            'columns': columns,
            'baseline': baseline,
            'ratio': ratio
        }
    }
    function calculate_columns_width() {
        zoom = 100;
        
        infos = gather_info();
        page = infos['page'];
        columns = infos['columns'];
        baseline = infos['baseline'];
        ratio = infos['ratio'];

        columns['width'] = (page['width']/columns['count'])-columns['gutter']+(columns['gutter']/columns['count']) - (page['margin_left']/columns['count']) - (page['margin_right']/columns['count']);
        
        baseline = {
            'size': get_size(e_baseline,e_baseline_unit),
            'color': e_baseline_color.val()
        };
        
        ratio = MAX_CANVAS_WIDTH/page['width'];
        
        converted = convert_to_unit(columns['width'],columns['width_unit']);
        e_columns_width.val(converted.toFixed(2));
        if ((converted.toFixed(2) % 1) == 0) {
            e_columns_width.addClass('integer');
        } else {
            e_columns_width.removeClass('integer');
        }
    }
    function calculate_gutter_width() {
        infos = gather_info();
        page = infos['page'];
        columns = infos['columns'];
        baseline = infos['baseline'];
        ratio = infos['ratio'];

        if (columns['count'] > 1) {
            inner_width = page['width']-page['margin_left']-page['margin_right'];
            gutter = (inner_width-(columns['width']*columns['count']))/(columns['count']-1);
            converted = gutter/UNITS[columns['gutter_unit']];
        } else {
            converted = 0;
        }
        
        e_columns_gutter.unbind('change');
        e_columns_gutter.val(converted.toFixed(2));
        if ((converted.toFixed(2) % 1) == 0) {
            e_columns_gutter.addClass('integer');
        } else {
            e_columns_gutter.removeClass('integer');
        }
        e_columns_gutter.change(calculate_columns_width);
    }
    function draw() {
        infos = gather_info();
        page = infos['page'];
        columns = infos['columns'];
        baseline = infos['baseline'];
        ratio = infos['ratio'];
        canvas_width = page['width']*ratio;
        canvas_height = page['height']*ratio;

        CANVAS_DIV.html(''); //reset
        CANVAS_DIV.css({width: canvas_width});
        var canvas = Raphael('canvas', canvas_width, canvas_height);
        
        page_scaled = {
            'width': page['width']*ratio,
            'height': page['height']*ratio,
            'margin_top': page['margin_top']*ratio,
            'margin_bottom': page['margin_bottom']*ratio,
            'margin_left': page['margin_left']*ratio,
            'margin_right': page['margin_right']*ratio
        };
        columns_scaled = {
            'count':columns['count'],
            'width': columns['width']*ratio,
            'width_unit': columns['width_unit'],
            'gutter': columns['gutter']*ratio,
            'gutter_unit': columns['gutter_unit'],
            'color': columns['color']
        };
        baseline_scaled = {
            'size': baseline['size']*ratio,
            'color': baseline['color']
        };
            
        $('#zoom').text(zoom.toFixed(2)+'%');
        draw_columns(canvas, page_scaled, columns_scaled);
        draw_baseline(canvas, page_scaled, baseline_scaled);
        draw_quotes(canvas, page_scaled, columns_scaled, baseline_scaled);
    }
    function draw_columns(canvas, page, columns) {
        col_height = page['height']-page['margin_top']-page['margin_bottom'];

        col_rects = canvas.set();
        col_gutters = canvas.set();
                
        for (i=0;i<columns['count'];i++) {
            x = page['margin_left'] + (i*(columns['width']+columns['gutter']))
            col = canvas.rect(x, page['margin_top'], columns['width'], col_height);
            col_rects.push(col);

            if (i<columns['count']-1) {
                gut = canvas.rect(x+columns['width'], page['margin_top'], columns['width'], col_height)
                col_gutters.push(gut);
            }
        }
        
        col_gutters.attr('fill','white');
        col_gutters.attr('stroke','none');
        col_rects.attr('fill',columns['color']);
        col_rects.attr('stroke','none');
    }

    function draw_quotes(canvas, page, columns, baseline) {
        col_padding = 5;
        
        quotes = canvas.set();
        lines = canvas.set();
        
        if (baseline['size'] > 6) {
            step = baseline['size']*2;
        } else {
            step = 24;
        }
        
        x0 = page['margin_left'];
        y0 = page['margin_top'];
        for (i=1;i<=columns['count'];i++) {
            w = (columns['width']*i)+(columns['gutter']*(i-1));
            x1 = x0+w;
            y0 += step;
            line = canvas.path().moveTo(x0,y0).lineTo(x1,y0).andClose();
            open = canvas.path().moveTo(x0,y0-2).lineTo(x0,y0+2).andClose();
            close = canvas.path().moveTo(x1,y0-2).lineTo(x1,y0+2).andClose();
            lines.push(line);
            lines.push(open);
            lines.push(close);
            
            y0 += -10;
            quote = canvas.text(x0+(w/2), y0, i+': '+ convert_to_unit((w/ratio),columns['width_unit']).toFixed(2)+columns['width_unit']);
            quotes.push(quote);
            y0 += 10;
        }
        quotes.attr('text-anchor', 'middle');
        quotes.attr('fill', 'purple');
        quotes.attr('background', 'white');
        lines.attr('stroke','purple');
        
    }
    function draw_rows(canvas, page, rows,ratio) {
        row_padding = 5;

        row_width = page['width']-page['margin_left']-page['margin_right'];

        row_rects = canvas.set();
        row_quotes = canvas.set();
        row_gutters = canvas.set();
        row_gut_quotes = canvas.set();
                
        for (i=0;i<rows['count'];i++) {
            x = page['margin_left'] + (i*(rows['width']+rows['gutter']))
            row = canvas.rect(x, page['margin_left'], rows['height'], row_width);
            $(row.node).hover(function() {
                row_quotes.show();
            }, function() {
                row_quotes.hide();
            });
            row_rects.push(row);

            if (i<rows['count']-1) {
                gut = canvas.rect(x+rows['height'], page['margin_left'], rows['height'], row_width)
                $(gut.node).hover(function() {
                    row_gut_quotes.show();
                }, function() {
                    row_gut_quotes.hide();
                });
                row_gutters.push(gut);
            }
        }
        for (i=0;i<rows['count'];i++) {
            x = page['margin_top'] + (i*(rows['height']+rows['gutter']))
            row_quote = canvas.text(x+row_padding, page['margin_left']+5+row_padding, convert_to_unit((rows['height']/ratio),rows['height_unit']).toFixed(2)+rows['height_unit']);
            row_quotes.push(row_quote);

            if (i<row['count']-1) {
                gut_quote = canvas.text(x+row['height'], page['margin_left']+5+row_padding, convert_to_unit((rows['gutter']/ratio),rows['gutter_unit']).toFixed(2)+rows['gutter_unit']);
                row_gut_quotes.push(gut_quote);
            }
        }
        
        row_gutters.attr('fill','white');
        row_gutters.attr('stroke','none');
        row_rects.attr('fill',rows['color']);
        row_rects.attr('stroke','none');
        row_quotes.hide();
        row_quotes.attr('text-anchor', 'start');
        row_quotes.attr('fill', 'purple');
        row_gut_quotes.hide();
        row_gut_quotes.attr('text-anchor', 'start');
        row_gut_quotes.attr('fill', 'green');
    }

    function draw_baseline(canvas, page, baseline) {
        if (baseline['size'] > 0) {
            baselines = canvas.set();

            baseline_x2 = page['width']-page['margin_right'];
            baseline_y2 = page['height']-page['margin_bottom'];

            y = page['margin_top']+baseline['size'];
            while (y < baseline_y2) {
                line = canvas.path().moveTo(page['margin_left'], y).lineTo(baseline_x2,y).andClose();
                y += baseline['size'];
                baselines.push(line);
            }
            baselines.attr('stroke',baseline['color']);
        }
    }
    function refresh() {
        calculate_columns_width();
        calculate_gutter_width();
        draw();
    }
    refresh();
});
