/*
 * Created on 2005-04-05
 *
 * Part of the Symbian development plug-in for Eclipse
 * Copyright (C) Mikołaj Zalewski, 2005
 */
package pl.zalewski.mikolaj.symbdev.core.internal.mmpmodel;

import java.util.Iterator;
import java.util.LinkedList;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jface.util.Assert;
import org.eclipse.swt.widgets.Listener;

import pl.zalewski.mikolaj.symbdev.SymbdevPlugin;
import pl.zalewski.mikolaj.symbdev.core.mmpmodel.IMMPBitmapContainer;
import pl.zalewski.mikolaj.symbdev.core.mmpmodel.MMPBitmapReference;
import pl.zalewski.mikolaj.symbdev.core.mmpmodel.MMPFileReference;
import pl.zalewski.mikolaj.symbdev.core.mmpmodel.MMPModelException;

/**
 * An implementation of the bitmap container interface which stores
 * all the information in memory (no file synchronization is done.
 * Subclasses does it).
 * 
 * @author mikolaj
 */
public class BitmapContainer implements IMMPBitmapContainer {

    public BitmapContainer() {
        super();
    }

    /**
     * Allways throws IllegalStateException
     */
    public void addBitmap(IPath file, String depth) throws CoreException {
        throw new IllegalStateException();
    }
    
    public void addBitmap(MMPFileReference file, String depth) throws CoreException
    {
        fBitmaps.add(new MMPBitmapReference(file, depth));
        fDirty=true;
        fireChange();
    }

    public MMPBitmapReference[] getBitmaps() {
        return (MMPBitmapReference[])fBitmaps.toArray(new MMPBitmapReference[fBitmaps.size()]);
    }

    public void removeBitmap(int pos) throws CoreException {
        if (pos<0 || pos>=fBitmaps.size())
            throw new MMPModelException(MMPModelException.ITEM_NOT_FOUND, "Bitmap reference not found");
        fBitmaps.remove(pos);
        fDirty=true;
        fireChange();
    }

    public void moveBitmapUp(int pos) throws CoreException {
        if (pos==0)
            throw new MMPModelException(MMPModelException.INVALID_ARGUMENT, "Position to move up is 0");
        
        MMPBitmapReference bitmap;
        try {
	        bitmap=(MMPBitmapReference)fBitmaps.get(pos);
        }
        catch (IndexOutOfBoundsException e) {
            throw new MMPModelException(MMPModelException.ITEM_NOT_FOUND, "Bitmap reference not found");            
        }
        
        fBitmaps.remove(pos);
        fBitmaps.add(pos-1, bitmap);
        fDirty=true;
        fireChange();
    }

    public void moveBitmapDown(int pos) throws CoreException {
        if (pos==fBitmaps.size()-1)
            throw new MMPModelException(MMPModelException.INVALID_ARGUMENT, "Position to move up is 0");        
        MMPBitmapReference bitmap;
        try {
	        bitmap=(MMPBitmapReference)fBitmaps.get(pos);
        }
        catch (IndexOutOfBoundsException e) {
            throw new MMPModelException(MMPModelException.ITEM_NOT_FOUND, "Bitmap reference not found");            
        }
        
        fBitmaps.remove(pos);
        fBitmaps.add(pos+1, bitmap);
        fDirty=true;
        fireChange();
    }

    public void setBitmapDepth(int pos, String newDepth) throws CoreException{
        MMPBitmapReference bitmap;
        try {
	        bitmap=(MMPBitmapReference)fBitmaps.get(pos);
        }
        catch (IndexOutOfBoundsException e) {
            throw new MMPModelException(MMPModelException.ITEM_NOT_FOUND, "Bitmap reference not found");            
        }
        bitmap.fDepth=newDepth;
        fireChange();
        fDirty=true;
    }
    
    public boolean copyFrom(BitmapContainer m)
    {
        boolean mod=false;
        fDirty=false;
        if (!MMPModel.isEqual(fBitmaps, m.fBitmaps))
        {
            fBitmaps=new LinkedList();
            Iterator it=m.fBitmaps.iterator();
            while (it.hasNext())
            {
                MMPBitmapReference ref=(MMPBitmapReference)it.next();
                fBitmaps.add(ref.clone());
            }
            mod=true;
        }
        return mod;
    }
    
    public void fireChange()
    {
        if (fFreezeFireChanges>0)
        {
            fFrozenChanges=true;
            return;
        }
        
        if (!fListener.isEmpty())
            SymbdevPlugin.getStandardDisplay().asyncExec(
                new Runnable() 
                {
                    public void run()
                    {
                        Iterator it=fListener.iterator();
                        while (it.hasNext())
                        {
                            Listener l=(Listener)it.next();
                            try {
                                l.handleEvent(null);
                            }
                            catch (Throwable t)
                            {
                                SymbdevPlugin.getDefault().getLog().log(
                                        SymbdevPlugin.createErrorStatus(0, t.getMessage(), t));
                            }
                        }
                    }
                });        
    }
    
    public void freezeFireChanges()
    {
        if (fFreezeFireChanges==0)
            fFrozenChanges=false;
        fFreezeFireChanges++;
    }
    
    public void unfreezeFireChanges()
    {
        fFreezeFireChanges--;
        Assert.isTrue(fFreezeFireChanges>=0);
        if (fFreezeFireChanges==0)
            if (fFrozenChanges)
                fireChange();
    }

    public void addChangeListener(Listener l)
    {
        fListener.add(l);
    }
    
    public void removeChangeListener(Listener l)
    {
        fListener.remove(l);
    }
    
    public boolean isConnected() {
        return fConnected;
    }
    
    int fFreezeFireChanges;
    boolean fFrozenChanges;
    boolean fConnected;
    boolean fDirty;
    LinkedList fBitmaps=new LinkedList();
    LinkedList fListener=new LinkedList();
}
