/*
 * PiAnoS (Picture Annotation System), A fingerprint examiner training tool
 * Copyright (C) 2011-2021 University of Lausanne, Switzerland
 * https://ips-labs.unil.ch/pianos
 * 
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option) any
 * later version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see http://www.gnu.org/licenses/.
 */

/**
 * @constructor
 */
function Pianos4ToolBrush( params )
{
    // ------------------------------
    // Constructor
    // ------------------------------
    
    params = params || {};
    
    // ------------------------------
    // Public methods
    // ------------------------------
    
    this.getName = function()
    {
        return 'brush';
    }

    this.getLabel = function()
    {
        return 'Brush';
    }

    this.getIcon = function()
    {
        return 'icons/tool_brush.png';
    }

    this.bind = function( aView )
    {
        assert( !view );
        view = aView;
    }

    this.unbind = function()
    {
        assert( view );
        view = null;
    }

    this.activate = function()
    {
    }

    this.deactivate = function()
    {
    }

    this.onMouseDown = function( pos )
    {
        assert( points.length == 0 );
        
        points.push( pos );
        
        var svgCanvas = view.dom().find( '.pianos4_view_canvas' );
        h5canvasOffset = svgCanvas.offset();
        h5canvas = $( '<canvas />' ).attr( 'width', svgCanvas.width() ).attr( 'height', svgCanvas.height() ).css( 'position', 'absolute' ).css( 'top', h5canvasOffset.top + 'px' )
            .css( 'left', h5canvasOffset.left + 'px' ).css( 'z-index', 2000 ).width( svgCanvas.width() ).height( svgCanvas.height() ).appendTo( 'body' );
        ctx = h5canvas.get( 0 ).getContext( '2d' );
        
        view.getSVG().selectAll( 'image.pianos4_tool_brush_result' ).remove();
        
        if( prevData )
        {
            ctx.globalCompositeOperation = 'source-over';
            // ctx.globalCompositeOperation = 'destination-atop';
            ctx.putImageData( prevData, 0, 0 );
        }
        
        // ctx.fillRect(10,10,100,100);
        ctx.lineCap = 'round';
        ctx.lineJoin = 'round';
        ctx.lineWidth = width;
        var rgba = [
            0, 0, 0, 0
        ];
        for( var i = 0; i < 3; ++i )
            rgba[ i ] = parseInt( color.substr( 1 + 2 * i, 2 ), 16 );
        rgba[ 3 ] = opacity;
        log( rgba );
        ctx.strokeStyle = 'rgba(' + rgba.join( ',' ) + ')';
        ctx.globalCompositeOperation = 'destination-atop';
        
        var p = unproject( pos );
        ctx.beginPath();
        ctx.moveTo( p[ 0 ], p[ 1 ] );
        ctx.lineTo( p[ 0 ], p[ 1 ] );
        ctx.stroke();
    }

    this.onMouseMove = function( pos )
    {
        assert( points.length >= 1 );
        
        points.push( pos );
        
        var p = unproject( pos );
        // ctx.fillCircle(p[0]-5,p[1],10);
        
        ctx.lineTo( p[ 0 ], p[ 1 ] );
        ctx.stroke();
    }

    this.onMouseUp = function( pos )
    {
        log( 'Created a path of ' + points.length + ' points' );
        assert( h5canvas );
        points = [];
        
        var data = ctx.getImageData( 0, 0, h5canvas.attr( 'width' ), h5canvas.attr( 'height' ) );
        log( h5canvas.get( 0 ).toDataURL() );
        prevData = data;
        
        view.getSVG().append( 'svg:image' ).classed( 'pianos4_tool_brush_result', true ).attr( 'width', h5canvas.attr( 'width' ) ).attr( 'height', h5canvas.attr( 'height' ) )
            .attr( 'xlink:href', h5canvas.get( 0 ).toDataURL() );
        
        pianos.ajax( {
            pendingMessage: 'Saving image',
            type: 'post',
            processData: false,
            contentType: 'application/json',
            url: 'http://localhost:8081/uflr?action=image&type=debug_save',
            data: JSON.stringify( h5canvas.get( 0 ).toDataURL() ),
            success: function( data )
            {
                if( !data.success )
                {
                    toastr.error( data.exception, '', { timeout: 5000 } );
                    return;
                }
                
                log( data.ret );
            },
            error: function( xhr, status, error )
            {
                toastr.error( ( error ? error : 'connection failed' ), 'HTTP error (code ' + xhr.status + ')', { timeout: 5000 } );
            },
        } );
        
        h5canvas.remove();
        h5canvas = null;
        h5canvasOffset = null;
        ctx = null;
        
        return true;
    }

    this.getOptionsPanel = function()
    {
        if( !options )
        {
            var panel = $( '<div class="pianos4_brush_options" />' );
            
            var selectColorCallback = function()
            {
                if( $( this ).attr( 'data-color' ) != color )
                {
                    color = $( this ).attr( 'data-color' );
                    $( this ).parents( '._content' ).find( '.pianos4_tool_color' ).removeCSS( 'border-color' );
                    $( this ).css( 'border-color', '#aaaaaa' );
                }
            };
            
            Pianos4ToolRidge.createColorPicker( panel, selectColorCallback, 'standard' );
            
            var initialColor;
            initialColor = panel.find( '.pianos4_tool_color:first' );
            color = initialColor.attr( 'data-color' );
            initialColor.css( 'border-color', '#aaaaaa' );
            
            panel.append( createToolSlider( 'Width', {
                min: 1,
                max: 50,
                value: width,
                onSlide: function( value )
                {
                    width = value;
                },
                unit: 'pt',
            } ) );
            
            panel.append( createToolSlider( 'Opacity', {
                min: 1,
                max: 100,
                value: 100.0 * opacity,
                onSlide: function( value )
                {
                    opacity = value / 100.0;
                },
                unit: '%',
            } ) );
            
            options = panel;
        }
        
        return options;
    }

    this.cancel = function()
    {
        points = [];
        if( h5canvas )
            h5canvas.remove();
        h5canvas = null;
        h5canvasOffset = null;
        ctx = null;
    }

    this.getHelp = function()
    {
        return Pianos4Help.compile( [
            'Use the brush tool to do whatever a brush is meant to do.',
        ] );
    }

    // ------------------------------
    // Private variables
    // ------------------------------
    
    var self = this;
    var view = null;
    var points = [];
    var color = '#ff0000';
    var width = 20.0;
    var opacity = 0.85;
    var options = null;
    var cycle = true;
    var h5canvas = null;
    var h5canvasOffset = null;
    var ctx = null;
    var prevData = null;
    
    // ------------------------------
    // Private functions
    // ------------------------------
    
    var unproject = function( pos )
    {
        assert( view && h5canvas && h5canvasOffset );
        var p = view.getAbsPos( pos );
        p[ 0 ] -= h5canvasOffset.left;
        p[ 1 ] -= h5canvasOffset.top;
        return p;
    }
}
