/*******************************************************************************
* Copyright (c)                                                                *
*           2005   Tristan Allwood,                                            *
*           2005   Daniel Burke,                                               *
*           2005   Marc Hull,                                                  *
*           2005   Ekaterina Itskova,                                          *
*           2005   Steve Zymler                                                *
*                                                                              *
* Permission is hereby granted, free of charge, to any person obtaining a      *
* copy of this software and associated documentation files (the                *
* "Software"), to deal in the Software without restriction, including          *
* without limitation the rights to use, copy, modify, merge, publish,          *
* distribute, sublicense, and/or sell copies of the Software, and to           *
* permit persons to whom the Software is furnished to do so, subject to        *
* the following conditions:                                                    *
*                                                                              *
* The above copyright notice and this permission notice shall be included      *
* in all copies or substantial portions of the Software.                       *
*                                                                              *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS      *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF                   *
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.       *
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY         *
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,         *
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE            *
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                       *
*******************************************************************************/
/*
 * Created on 08-Nov-2004
 */
package uk.ac.ic.doc.kevlar.gui.internal.layout;


import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.swt.graphics.Point;

import uk.ac.ic.doc.kevlar.gui.internal.widgets.tab.Tab;

/**
 * @author Marc
 **/
public class LayoutImp implements ILayout {
       
    private static final int CELL_SIZE = 20;    
    
    private LayoutGrid layoutGrid;
    
    
    public LayoutImp()
    {    	
    	layoutGrid = new LayoutGrid(); 
    }
    
    private LayoutData getLayoutData(ILayoutProgram program) {
        
        LayoutData data = (LayoutData)program.getLayoutData();
        
        if (data == null) {
            
            Point pos = program.getPosition();
            
            if( pos.x == 0 && pos.y == 0)
            {
                data = new LayoutData( program.getSize() );             
            }
            else
            {
                data = new LayoutData( pos, program.getSize() );
            }
            program.setLayoutData(data);
            
        }
        program.setPosition(data.position);
        
        return data;
        
    }
    
    /* (non-Javadoc)
     * @see uk.ac.ic.doc.kevlar.gui.internal.layout.ILayout#addProgram(uk.ac.ic.doc.kevlar.gui.internal.layout.ILayoutProgram)
     */
    public void addProgram(ILayoutProgram program) {
        
        program.setPosition(getLayoutData(program).position);
        
    }

    /* (non-Javadoc)
     * @see uk.ac.ic.doc.kevlar.gui.internal.layout.ILayout#suggestProgramPosition(uk.ac.ic.doc.kevlar.gui.internal.layout.ILayoutProgram, org.eclipse.swt.graphics.Point)
     */
    public void suggestProgramPosition(ILayoutProgram program, Point position) {

        LayoutData data = getLayoutData(program);
        data.setPosition( new Point((int)(Math.round((double)position.x/CELL_SIZE))*CELL_SIZE, (int)(Math.round((double)position.y/CELL_SIZE))*CELL_SIZE));
        program.setPosition(data.position);
        
        layoutGrid.addProgram( program, false );
                
    }
    
    public void suggestProgramAutoPosition(ILayoutProgram program, Point position) {

        LayoutData data = getLayoutData(program);
        data.setPosition( new Point((int)(Math.round((double)position.x/CELL_SIZE))*CELL_SIZE, (int)(Math.round((double)position.y/CELL_SIZE))*CELL_SIZE));
        program.setPosition(data.position);
        
        layoutGrid.addProgram( program, true );
                
    }


    /* (non-Javadoc)
     * @see uk.ac.ic.doc.kevlar.gui.internal.layout.ILayout#forceProgramSize(uk.ac.ic.doc.kevlar.gui.internal.layout.ILayoutProgram, org.eclipse.swt.graphics.Point)
     */
    public void forceProgramSize(ILayoutProgram program, Point size) {
        
        LayoutData data = getLayoutData(program);
        data.setSize( size );
        
        layoutGrid.addProgram( program, false );
    }

    /* (non-Javadoc)
     * @see uk.ac.ic.doc.kevlar.gui.internal.layout.ILayout#removeProgram(uk.ac.ic.doc.kevlar.gui.internal.layout.ILayoutProgram)
     */
    public void removeProgram(ILayoutProgram program) {
        
        layoutGrid.removeProgram( program );
        
    }

    /* (non-Javadoc)
     * @see uk.ac.ic.doc.kevlar.gui.internal.layout.ILayout#addPipe(uk.ac.ic.doc.kevlar.gui.internal.layout.ILayoutPipe, org.eclipse.swt.graphics.Point, org.eclipse.swt.graphics.Point)
     */
    public void addPipe(ILayoutPipe pipe) {
        
        pipe.removePoints();
        
        layoutGrid.addPipe( pipe );
        
    }
        

    /* (non-Javadoc)
     * @see uk.ac.ic.doc.kevlar.gui.internal.layout.ILayout#alterPipe(uk.ac.ic.doc.kevlar.gui.internal.layout.ILayoutPipe, org.eclipse.swt.graphics.Point, org.eclipse.swt.graphics.Point)
     */
    public void alterPipe(ILayoutPipe pipe, Point start, Point end) {
       
        layoutGrid.alterPipe( pipe, start, end );        
    }

    /* (non-Javadoc)
     * @see uk.ac.ic.doc.kevlar.gui.internal.layout.ILayout#removePipe(uk.ac.ic.doc.kevlar.gui.internal.layout.ILayoutPipe)
     */
    public void removePipe(ILayoutPipe pipe) {
    	layoutGrid.removePipe( pipe );
    }

    /* (non-Javadoc)
     * @see uk.ac.ic.doc.kevlar.gui.internal.layout.ILayout#startQuickMove()
     */
    public void startQuickMove() {
    }

    /* (non-Javadoc)
     * @see uk.ac.ic.doc.kevlar.gui.internal.layout.ILayout#stopQuickMove()
     */
    public void stopQuickMove() {
    }

    /* (non-Javadoc)
     * @see uk.ac.ic.doc.kevlar.gui.internal.layout.ILayout#newProgramPosition()
     */
    public Point newProgramPosition() {
        // TODO Auto-generated method stub
        return new Point(40, 40);
    }

    /* (non-Javadoc)
     * @see uk.ac.ic.doc.kevlar.gui.internal.layout.ILayout#addProgram(uk.ac.ic.doc.kevlar.gui.internal.layout.ILayoutProgram, org.eclipse.swt.graphics.Point)
     */
    public void addProgram(ILayoutProgram program, Point suggested) {
        
        addProgram(program);
        suggestProgramPosition(program, suggested);
        
    }

    /* (non-Javadoc)
     * @see uk.ac.ic.doc.kevlar.gui.internal.layout.ILayout#addProgramAsInput(uk.ac.ic.doc.kevlar.gui.internal.layout.ILayoutProgram, uk.ac.ic.doc.kevlar.gui.internal.layout.ILayoutProgram)
     */
    public void addProgramAsInput(ILayoutProgram program, ILayoutProgram output) {

        addProgram(program);
        suggestProgramAutoPosition(program, new Point(output.getPosition().x+output.getSize().x+LayoutGrid.SPACING, output.getPosition().y));
        
    }

    /* (non-Javadoc)
     * @see uk.ac.ic.doc.kevlar.gui.internal.layout.ILayout#addProgramAsOutput(uk.ac.ic.doc.kevlar.gui.internal.layout.ILayoutProgram, uk.ac.ic.doc.kevlar.gui.internal.layout.ILayoutProgram)
     */
    public void addProgramAsOutput(ILayoutProgram program, ILayoutProgram input) {

        addProgram(program);
        suggestProgramAutoPosition(program, new Point(input.getPosition().x-program.getSize().x-LayoutGrid.SPACING, input.getPosition().y));
        
    }

}
