/*
 * MMCDGUIHandler.java
 * 
 * Created on 29 May�s 2005 Pazar, 02:37
 */

package com.isoft.mmcd.application.handlers ;

import com.isoft.mmcd.exceptions.* ;
import com.isoft.mmcd.engine.* ;
import com.isoft.mmcd.library.CLibrary ;
import com.isoft.mmcd.skin.* ;
import com.isoft.mmcd.skin.widgets.MMCDFontChooser ;
import com.isoft.mmcd.skin.widgets.MMCDKeyboardPopup ;
import com.isoft.mmcd.skin.widgets.MMCDPopUpMenu ;
import com.isoft.mmcd.utils.Options ;
import com.isoft.mmcd.utils.cfgreader.* ;
import com.isoft.mmcd.application.events.* ;
import com.isoft.mmcd.application.rnk.RNKApplication ;

import java.util.* ;
import java.awt.* ;
import java.awt.datatransfer.StringSelection ;

import java.awt.geom.* ;
import javax.swing.* ;

import javax.swing.text.JTextComponent ;

/**
 * 
 * @author Fatih
 */
public class MMCDGUIHandler implements MMCDEventHandler, java.io.Serializable, TimerHandler
{
    public static class ScrollData
    {
        public static final int INITIAL = 1 ;

        public static final int FINAL = 2 ;

        public static final int INITIAL_TO_FINAL = 3 ;

        public static final int FINAL_TO_INITIAL = 4 ;

        public boolean active = false ;

        public int state = INITIAL ;

        public Rectangle pos0 = new Rectangle( 0, 0, 0, 0 ) ;

        public Rectangle pos1 = new Rectangle( 0, 0, 0, 0 ) ;

        public Rectangle2D.Double pos0_r = new Rectangle2D.Double( 0, 0, 0, 0 ) ;

        public Rectangle2D.Double pos1_r = new Rectangle2D.Double( 0, 0, 0, 0 ) ;

        public Rectangle cur = new Rectangle( 0, 0, 0, 0 ) ;

        public Rectangle2D.Double cur_r = new Rectangle2D.Double( 0, 0, 0, 0 ) ;

        public double t = 0 ;

        public double duration = 0 ; // total animation length,
        
        public boolean isResizeAll = false ;
    } ;

    protected Engine engine = null ;

    protected long interval = 10 ;

    protected long lastActivationTime = 0 ;

    protected boolean active = false ;

    protected ArrayList widgetsToTrack = new ArrayList( ) ;

    protected Hashtable scrollDataPool = new Hashtable( ) ;

    /** Creates a new instance of MMCDDefaultActionsHandler */
    public MMCDGUIHandler( )
    {
        /* nothing to do */
    }

    public void init( Engine engine, MCCompoundProperty parameters )
    {
        this.engine = engine ;
        if( !engine.getSkin( ).getGuiThread( ).existsInQueue( this ) )
            engine.getSkin( ).getGuiThread( ).add( this ) ;

        MCCompoundProperty cp = parameters.getCompoundProperty( "@action_0" ) ;
        int i = 0 ;
        while( cp != null )
        {
            String type = cp.getAtomicProperty( "$type" ).getValue( ) ;
            ScrollData sd ;
            if( "KAYDIR".equals( type ) )
            {
                Widget w = engine.getSkin( ).getWidgetPool( ).getWidget( cp.getAtomicProperty( "$widget" ).getValue( ) ) ;
                widgetsToTrack.add( w ) ;
                sd = new ScrollData( ) ;
                scrollDataPool.put( w, sd ) ;
                sd.pos0 = cp.getAtomicProperty( "$initial" ).getRectangle( ) ;
                sd.pos1 = cp.getAtomicProperty( "$final" ).getRectangle( ) ;
                sd.pos0_r = cp.getAtomicProperty( "$initial_r" ).getDoubleRectangle( ) ;
                sd.pos1_r = cp.getAtomicProperty( "$final_r" ).getDoubleRectangle( ) ;
                sd.duration = cp.getAtomicProperty( "$duration" ).getDecimalValue( ) ;
                sd.isResizeAll = cp.getAtomicProperty( "$isrepositionall" ).getBooleanValue( ) ;
                sd.t = 0.0 ;
            }

            cp = parameters.getCompoundProperty( "@action_" + ( ++i ) ) ;
        }

        System.err.println( "GUI Handler instance initialized" ) ;
    }

    public void setHandledObject( Object object )
    {
        /* to be added later */
    }

    public void initForObject( MCCompoundProperty cp )
    {
        /* to be added later */
    }

    public void initForTimer( )
    {
        active = false ;
    }

    public void setTimerInterval( long interval )
    {
        this.interval = interval ;
    }

    public long getTimerInterval( )
    {
        return this.interval ;
    }

    public long getLastActivationTime( )
    {
        return lastActivationTime ;
    }

    public void setLastActivationTime( long lastActivationTime )
    {
        this.lastActivationTime = lastActivationTime ;
    }

    public boolean isActive( )
    {
        return active ;
    }

    public boolean isFinished( )
    {
        return false ;
    }

    public void onTimer( long time )
    {
        // handle scrolls
        // System.err.println( "Currently gui handler is running" ) ;
        if( getLastActivationTime( ) == 0 )
            setLastActivationTime( time ) ;
        double dt = ( time - getLastActivationTime( ) ) * 0.001 ;
        ScrollData sd ;
        ResizableWidget rw ;
        active = false ; // first unactivate the thread
        boolean isResize = true ;
        for( int i = 0; i < widgetsToTrack.size( ); ++i )
        {
            sd = ( ScrollData )scrollDataPool.get( getWidget( i ) ) ;
            if( sd != null && sd.active )
            {
                if( sd.state == ScrollData.INITIAL_TO_FINAL )
                {
                    // System.err.println( "initial to final.." ) ;
                    active = true ; // re activate, since there are widgets to
                    // scroll
                    sd.t += dt ;
                    if( sd.t >= sd.duration )
                    {
                        sd.t = sd.duration ;
                        sd.cur.setBounds( sd.pos1 ) ;
                        sd.cur_r.setRect( sd.pos1_r ) ;
                        sd.state = ScrollData.FINAL ;
                        sd.active = false ;
                    }
                    else
                    {
                        getIntermediateRect( sd.pos0, sd.pos1, sd.t / sd.duration, sd.cur ) ;
                        getIntermediateDoubleRect( sd.pos0_r, sd.pos1_r, sd.t / sd.duration, sd.cur_r ) ;
                        isResize = isResize && sd.active ;
                    }
                }
                else if( sd.state == ScrollData.FINAL_TO_INITIAL )
                {
                    // System.err.println( "final to initial.." ) ;
                    active = true ; // re activate, since there are widgets to
                    // scroll
                    sd.t += dt ;
                    if( sd.t >= sd.duration )
                    {
                        sd.t = sd.duration ;
                        sd.cur.setBounds( sd.pos0 ) ;
                        sd.cur_r.setRect( sd.pos0_r ) ;
                        sd.state = ScrollData.INITIAL ;
                        sd.active = false ;
                    }
                    else
                    {
                        getIntermediateRect( sd.pos1, sd.pos0, sd.t / sd.duration, sd.cur ) ;
                        getIntermediateDoubleRect( sd.pos1_r, sd.pos0_r, sd.t / sd.duration, sd.cur_r ) ;
                    }
                }

                rw = ( ResizableWidget )getWidget( i ) ;
                rw.getDynamicWidgetBounds( ).init( sd.cur_r ) ;
                rw.getDynamicWidgetBounds( ).setAbsoluteRect( sd.cur.x, sd.cur.y, sd.cur.width, sd.cur.height ) ;
                if( rw instanceof ScrollableWidget )
                    rw.resizeWidget( ( ( ScrollableWidget )rw ).getScrollPane( ).getParent( ).getBounds( ) ) ;
                else
                    rw.resizeWidget( ( ( JComponent )rw ).getParent( ).getBounds( ) ) ;
            }
        }
        if( !active && isResize )
        {
            System.err.println( "Operation done. Now resizing.." ) ;
            engine.getApplication( ).getMainWindow( ).invalidate( ) ;
            engine.getApplication( ).getMainWindow( ).getContentPane( ).invalidate( ) ;
            engine.getSkin( ).resizeRecursively( engine.getApplication( ).getMainWindow( ).getContentPane( ) ) ;
        }
    }

    protected Rectangle getIntermediateRect( Rectangle r0, Rectangle r1, double dist, Rectangle res )
    {
        if( res == null )
            res = new Rectangle( ) ;
        res.x = ( int )( ( r1.x - r0.x ) * dist + r0.x ) ;
        res.y = ( int )( ( r1.y - r0.y ) * dist + r0.y ) ;
        res.width = ( int )( ( r1.width - r0.width ) * dist + r0.width ) ;
        res.height = ( int )( ( r1.height - r0.height ) * dist + r0.height ) ;
        return res ;
    }

    protected Rectangle2D.Double getIntermediateDoubleRect( Rectangle2D.Double r0, Rectangle2D.Double r1, double dist, Rectangle2D.Double res )
    {
        if( res == null )
            res = new Rectangle2D.Double( ) ;
        res.x = ( ( r1.x - r0.x ) * dist + r0.x ) ;
        res.y = ( ( r1.y - r0.y ) * dist + r0.y ) ;
        res.width = ( ( r1.width - r0.width ) * dist + r0.width ) ;
        res.height = ( ( r1.height - r0.height ) * dist + r0.height ) ;
        return res ;
    }

    public Widget getWidget( int index )
    {
        return ( Widget )widgetsToTrack.get( index ) ;
    }

    public void handleEvent( EventQueueElement eqe ) throws MMCDException
    {
        MMCDEvent event = eqe.event ;
        // System.err.println( "Event handling began:" + event.getName( ) ) ;
        try
        {
            MCCompoundProperty cp = event.getDecleration( ).getCompoundProperty( "@action_0" ) ;
            int i = 0 ;
            while( cp != null )
            {
                String type = cp.getAtomicProperty( "$type" ).getValue( ) ;
                if( "MESAJ".equals( type ) )
                {
                    String msg = "" ;
                    String title = cp.getAtomicProperty( "$baslik" ).getValue( ) ;
                    if( cp.getAtomicProperty( "$mesaj" ) != null )
                        msg = cp.getAtomicProperty( "$mesaj" ).getValue( ) ;
                    else if( eqe.eventData != null )
                        msg = eqe.eventData.toString( ) ;
                    JOptionPane.showMessageDialog( null, msg, title, JOptionPane.INFORMATION_MESSAGE ) ;
                }
                else if( "GIZLE".equals( type ) )
                {
                    JComponent jc = engine.getSkin( ).getWidgetPool( ).getJComponent( cp.getAtomicProperty( "$widget" ).getValue( ) ) ;

                    jc.setVisible( false ) ;
                }
                else if( "COPY".equals( type ) )
                {
                    MMCDPopUpMenu pm = ( MMCDPopUpMenu )( ( JComponent )eqe.eventData ).getParent( ) ;

                    //                    System.out.println( "ParentName:" + pm.getInvoker( ).getClass( ).getName( ) ) ;
                    //                    System.out.println( "Selection:" + pm.getInvoker( ).getAccessibleContext( ).getAccessibleText( ).getSelectedText( ) ) ;
                    if( pm.getInvoker( ) instanceof JTextComponent )
                        ( ( JTextComponent )pm.getInvoker( ) ).copy( ) ;
                    else if( pm.getInvoker( ).getAccessibleContext( ).getAccessibleText( ).getSelectedText( ) != null )
                    {
                        StringSelection ss = new StringSelection( pm.getInvoker( ).getAccessibleContext( ).getAccessibleText( ).getSelectedText( ) ) ;
                        Toolkit.getDefaultToolkit( ).getSystemClipboard( ).setContents( ss, ss ) ;
                    }
                }
                else if( "CUT".equals( type ) )
                {
                    MMCDPopUpMenu pm = ( MMCDPopUpMenu )( ( JComponent )eqe.eventData ).getParent( ) ;

                    if( pm.getInvoker( ) instanceof JTextComponent )
                        ( ( JTextComponent )pm.getInvoker( ) ).cut( ) ;

                }
                else if( "PASTE".equals( type ) )
                {
                    MMCDPopUpMenu pm = ( MMCDPopUpMenu )( ( JComponent )eqe.eventData ).getParent( ) ;

                    if( pm.getInvoker( ) instanceof JTextComponent )
                        ( ( JTextComponent )pm.getInvoker( ) ).paste( ) ;

                }
                else if( "show_fontchooser".equals( type ) )
                {
                    MMCDFontChooser fc = new MMCDFontChooser( ) ;
                    fc.setVisible( true ) ;
                    System.err.println( "Gösterdim" ) ;
                }
                else if( "KEYBOARD".equals( type ) )
                {
                    MMCDPopUpMenu pm = ( MMCDPopUpMenu )( ( JComponent )eqe.eventData ).getParent( ) ;

                    System.err.println( "Keyboard a girdik:" + pm.getInvoker( ).getClass( ).getName( ) ) ;

                    //                    System.out.println( "ParentName:" + pm.getInvoker( ).getClass( ).getName( ) ) ;
                    //                    System.out.println( "Selection:" + pm.getInvoker( ).getAccessibleContext( ).getAccessibleText( ).getSelectedText( ) ) ;
                    if( pm.getInvoker( ) instanceof JTextComponent )
                    {
                        System.out.println( "ok, building kb.." ) ;
                        JTextComponent tc = ( JTextComponent )pm.getInvoker( ) ;
                        //MMCDKeyboardPopup kbp = new MMCDKeyboardPopup( ( Frame )SwingUtilities.getWindowAncestor( tc ) ) ;
                        // kbp.bindToComponent( tc ) ;
                        MMCDKeyboardPopup.getSharedInstance( ).bindToComponent( tc ) ;
                    }
                    else
                    {
                        System.out.println( "failure.. textfield is not a text component" ) ;
                    }

                }
                else if( "COPY_FROM_FOCUSED".equals( type ) )
                {
                    if( engine.getApplication( ).getMainWindow( ).getFocusOwner( ) instanceof JTextComponent )
                        ( ( JTextComponent )engine.getApplication( ).getMainWindow( ).getFocusOwner( ) ).copy( ) ;
                }
                else if( "CUT_FROM_FOCUSED".equals( type ) )
                {
                    if( engine.getApplication( ).getMainWindow( ).getFocusOwner( ) instanceof JTextComponent )
                        ( ( JTextComponent )engine.getApplication( ).getMainWindow( ).getFocusOwner( ) ).cut( ) ;
                }
                else if( "PASTE_TO_FOCUSED".equals( type ) )
                {
                    if( engine.getApplication( ).getMainWindow( ).getFocusOwner( ) instanceof JTextComponent )
                        ( ( JTextComponent )engine.getApplication( ).getMainWindow( ).getFocusOwner( ) ).paste( ) ;
                }
                else if( "GOSTER".equals( type ) )
                {
                    JComponent jc = engine.getSkin( ).getWidgetPool( ).getJComponent( cp.getAtomicProperty( "$widget" ).getValue( ) ) ;

                    jc.setVisible( true ) ;
                }
                else if( "GIZLE_GOSTER".equals( type ) )
                {
                    JComponent jc = engine.getSkin( ).getWidgetPool( ).getJComponent( cp.getAtomicProperty( "$widget" ).getValue( ) ) ;

                    jc.setVisible( !jc.isVisible( ) ) ;
                }
                else if( "BOYUTLANDIR".equals( type ) )
                {
                    ResizableWidget rw = ( ResizableWidget )engine.getSkin( ).getWidgetPool( ).getWidget( cp.getAtomicProperty( "$widget" ).getValue( ) ) ;
                    Rectangle2D.Double relPos = cp.getAtomicProperty( "$relposition" ).getDoubleRectangle( ) ;
                    Rectangle absPos = cp.getAtomicProperty( "$position" ).getRectangle( ) ;

                    rw.getDynamicWidgetBounds( ).init( relPos.x, relPos.y, relPos.width, relPos.height ) ;
                    rw.getDynamicWidgetBounds( ).setAbsoluteRect( absPos ) ;
                    if( rw instanceof ScrollableWidget )
                        rw.resizeWidget( ( ( ScrollableWidget )rw ).getScrollPane( ).getParent( ).getBounds( ) ) ;
                    else
                        rw.resizeWidget( ( ( JComponent )rw ).getParent( ).getBounds( ) ) ;

                    // engine.getSkin( ).resizeRecursively( engine.getApplication( ).getMainWindow( ).getContentPane( ) ) ;
                    engine.getSkin( ).resizeRecursively( ( ( JComponent )rw ).getParent( ) ) ;
                    engine.getApplication( ).getMainWindow( ).repaint( ) ;
                }
                else if( "PENCERE_GIZLE_GOSTER".equals( type ) )
                {
                    MMCDWindow jw = ( MMCDWindow )engine.getSkin( ).getWidgetPool( ).getWidget( cp.getAtomicProperty( "$widget" ).getValue( ) ) ;

                    jw.setVisible( !jw.isVisible( ) ) ;
                }
                else if( "KAYDIR".equals( type ) )
                {
                    Widget w = engine.getSkin( ).getWidgetPool( ).getWidget( cp.getAtomicProperty( "$widget" ).getValue( ) ) ;
                    if( scrollDataPool.get( w ) != null )
                    {
                        ScrollData sd = ( ScrollData )scrollDataPool.get( w ) ;
                        if( sd.state == ScrollData.INITIAL )
                        {
                            System.err.println( "Kaydırma başladı" ) ;
                            sd.state = ScrollData.INITIAL_TO_FINAL ;
                            sd.t = 0.0 ;
                            sd.active = true ;
                        }
                        else if( sd.state == ScrollData.FINAL )
                        {
                            System.err.println( "Ters Kaydırma başladı" ) ;
                            sd.state = ScrollData.FINAL_TO_INITIAL ;
                            sd.t = 0.0 ;
                            sd.active = true ;
                        }
                        else if( sd.state == ScrollData.INITIAL_TO_FINAL )
                        {
                            sd.state = ScrollData.FINAL_TO_INITIAL ;
                            sd.t = sd.duration - sd.t ;
                            sd.active = true ;
                        }
                        else if( sd.state == ScrollData.FINAL_TO_INITIAL )
                        {
                            sd.state = ScrollData.INITIAL_TO_FINAL ;
                            sd.t = sd.duration - sd.t ;
                            sd.active = true ;
                        }
                        active = true ;
                        setLastActivationTime( 0 ) ; // be sure we use correct
                        // time..
                    }
                }
                else if( "TETIKLE".equals( type ) )
                {
                    MMCDEvent mce = engine.getEventPool( ).getEvent( cp.getAtomicProperty( "$event" ).getValue( ) ) ;
                    boolean isNotQueued = false ;
                    if( cp.getAtomicProperty( "$notqueueed" ) != null )
                        isNotQueued = cp.getAtomicProperty( "$notqueued" ).getBooleanValue( ) ;
                    EventQueueElement newevt = new EventQueueElement( mce.getName( ), null ) ;
                    engine.getEventQueue( ).addEventToQueue( newevt, mce.getPriority( ), !isNotQueued ) ;
                }
                else if( "GOSTERX".equals( type ) )
                {
                    CLibrary clib = ( ( RNKApplication )this.engine.getApplication( ) ).getRNKLibrary( ) ;
                    int index = clib.getDynamicContent( ).getAllRequest( ).getFocsusedBookIndex( ) ;
                    index = 0 ;
                    JComponent jc = engine.getSkin( ).getWidgetPool( ).getJComponent( cp.getAtomicProperty( "$widget" ).getValue( ) + index ) ;

                    jc.setVisible( true ) ;
                }
                else if( "GIZLEX".equals( type ) )
                {
                    CLibrary clib = ( ( RNKApplication )this.engine.getApplication( ) ).getRNKLibrary( ) ;
                    int index = clib.getDynamicContent( ).getAllRequest( ).getFocsusedBookIndex( ) ;
                    index = 0 ;
                    JComponent jc = engine.getSkin( ).getWidgetPool( ).getJComponent( cp.getAtomicProperty( "$widget" ).getValue( ) + index ) ;

                    jc.setVisible( false ) ;
                }
                else if( "REFRESH_OPTIONS".equals( type ) )
                {
                    Options.getInstance( ).setPopup( null ) ;
                }
                else if( "TOGGLE_HELPER".equals( type ) )
                {
                    engine.getSkin( ).getGlassPaneManager( ).showHelper( !engine.getSkin( ).getGlassPaneManager( ).getIsHelperVisible( ) ) ;
                }
                else if( "RESET_KEYBOARD".equals( type ) )
                {
                    MMCDKeyboardPopup.resetSharedInstance( ) ;
                }

                cp = event.getDecleration( ).getCompoundProperty( "@action_" + ( ++i ) ) ;
            }
            // Thread.sleep( 1000 ) ;
        }
        // catch( InterruptedException ignore )
        // { }
        catch( Exception e )
        {
            e.printStackTrace( ) ;
            throw new MMCDException( e ) ;
        }
        //System.err.println( "Event handled:" + event.getName( ) + "\r\n---------\r\n" ) ;
    }
}