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

import java.io.File;
import java.util.HashMap;
import java.util.HashSet;
import java.util.regex.Pattern;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.TableWrapData;

import pl.zalewski.mikolaj.symbdev.SymbdevPlugin;
import pl.zalewski.mikolaj.symbdev.SymbianPrjNature;
import pl.zalewski.mikolaj.symbdev.core.mmpmodel.IMMPModel;
import pl.zalewski.mikolaj.symbdev.core.mmpmodel.MMPModelException;
import pl.zalewski.mikolaj.symbdev.ui.SymbdevImages;
import pl.zalewski.mikolaj.symbdev.utils.StringDialog;

/**
 * This section contains a list of libraries found in the SDK for
 * this project. There is a possibility to include libraries not
 * included on that list.
 * 
 * @author mikolaj
 */
public class LibrariesOptionsSection extends MMPSectionPart {

    static Pattern libsPattern=Pattern.compile(".*\\.lib", Pattern.CASE_INSENSITIVE);
    static Image libImage=SymbdevImages.LIBRARY.createImage();
    
    public LibrariesOptionsSection(Composite parent, FormToolkit toolkit,
            boolean debug, IMMPModel model, IProject project) {
        super(parent, toolkit, (!debug?"Libraries":"Debug libraries"),
                (!debug?"Select the static libraries to link into your program":
                    	"You can also select libraries that will be linked only in debug builds"), 2);
        fModel=model;
        fDebug=debug;
        
        fTable=toolkit.createTable(fContainer, SWT.NONE|SWT.CHECK);
        TableWrapData gd=new TableWrapData();
        gd.align=TableWrapData.FILL;
        gd.grabHorizontal=true;
        gd.heightHint=200;
        fTable.setLayoutData(gd);
        fTable.addSelectionListener(new SelectionListener() {
            public void widgetDefaultSelected(SelectionEvent e) { event(e); }
            public void widgetSelected(SelectionEvent e) { event(e); }
            void event(SelectionEvent e) { itemSelected((TableItem)e.item); }
        });
        
        
        // fill table
        IPath path=null;
        try {
            path=SymbianPrjNature.getLibsDirForProject(project);
        } catch (CoreException e) {
            boolean ignore=false;
            if (e.getStatus().getPlugin().equals(SymbdevPlugin.getUniqueIdentifier()))
            {
                int code=e.getStatus().getCode();
                if (code==SymbdevPlugin.ERROR_NO_SYMBIAN_NATURE ||
                    code==SymbdevPlugin.ERROR_NO_TOOL_CONFIG)
                    ignore=true;
            }
            if (!ignore)
                SymbdevPlugin.showError(e, "Error quering for libraries", getSection().getShell());
        }
        
        if (path!=null)
        {
            File dir=path.toFile();
            if (dir.exists() && dir.isDirectory())
            {
                String[] libs=dir.list();
                for (int i=0; i<libs.length; i++)
                    if (libsPattern.matcher(libs[i]).matches())
                        addLibraryWithImage(libs[i]);
            }
        }
        fDetectedCount=fTable.getItemCount();

        fAdd=toolkit.createButton(fContainer, "Add...", SWT.PUSH);
        fAdd.addListener(SWT.Selection, new Listener() {
            public void handleEvent(org.eclipse.swt.widgets.Event e) {
                addPushed();
            }
        });
        
        setupLibraries();
        
        fListener=new Listener() {
            public void handleEvent(org.eclipse.swt.widgets.Event e) {
                setupLibraries();
            }			
        };
        fModel.addChangeListener(IMMPModel.CHANGE_LIBRARIES, fListener);
        if (fDebug)
        {
            fDebugListener=new Listener() {
                public void handleEvent(org.eclipse.swt.widgets.Event e) {
                    setupLibraries();
                }
            };
            fModel.addChangeListener(IMMPModel.CHANGE_DEBUG_LIBRARIES, fDebugListener);
        }
        
        contentCreated();
    }
    
    TableItem createLibraryItem(String name)
    {
        TableItem ti=new TableItem(fTable, SWT.NONE);
        ti.setText(name);
        fTableLibraries.put(name.toUpperCase(),
                new Integer(fTable.getItemCount()-1));
        return ti;
    }
    
    void addLibrary(String name, boolean debug)
    {
        TableItem ti=createLibraryItem(name);
        ti.setChecked(true);
        if (!debug && fDebug)
            ti.setGrayed(true);
    }
        
    void addLibraryWithImage(String name)
    {
        TableItem ti=createLibraryItem(name);
        ti.setImage(libImage);
    }
    
    void setupLibraries()
    {
        if (fTable.isDisposed())
            return;
        
        String[] libs=fModel.getLibraries();
        HashSet libsSet=new HashSet();
        for (int i=0; i<libs.length; i++)
        {
            String libUpper=libs[i].toUpperCase();
            libsSet.add(libUpper);
            Integer libpos=(Integer)fTableLibraries.get(libUpper);
            if (libpos!=null)
            {
                fTable.getItem(libpos.intValue()).setChecked(true);
                if (fDebug)
                    fTable.getItem(libpos.intValue()).setGrayed(true);
            } else addLibrary(libs[i], false);
        }
        
        if (fDebug)
        {
            libs=fModel.getDebugLibraries();
            for (int i=0; i<libs.length; i++)
            {
                String libUpper=libs[i].toUpperCase();
                if (libsSet.contains(libUpper))  // from the LIBRARIES loop
                    continue;
                libsSet.add(libUpper);
                Integer libpos=(Integer)fTableLibraries.get(libUpper);
                if (libpos!=null)
                {
                    fTable.getItem(libpos.intValue()).setChecked(true);
                    fTable.getItem(libpos.intValue()).setGrayed(false);
                } else addLibrary(libs[i], false);
            }
        }
        
        int count=fTable.getItemCount();
        for (int i=0; i<count; i++)
        {
            String text=fTable.getItem(i).getText().toUpperCase();
            if (!libsSet.contains(text))
            {
                if (i<fDetectedCount)
                {
	                fTable.getItem(i).setChecked(false);
	                fTable.getItem(i).setGrayed(false);
                } else
                {
                    fTable.remove(i);
                    i--; count--;
                    libsSet.remove(text);
                    fTableLibraries.remove(text);
                }
            } else fTableLibraries.put(text, new Integer(i));
        }
    }
    
    void itemSelected(TableItem item)
    {
        if (item.getGrayed())
        {
            item.setChecked(true);
            return;
        }
        
        if (item.getChecked())
        {
            try {
                if (!fDebug)
                    fModel.addLibrary(item.getText());
                else fModel.addDebugLibrary(item.getText());
            }
            catch (CoreException e)
            {
                if (!MMPModelException.isMMPModelException(e,
                        MMPModelException.ITEM_EXISTS))
                    SymbdevPlugin.showError(e, "Error adding library",
                            getSection().getShell());
            }
        } else
        {
            String[] libs;
            if (!fDebug)
                libs=fModel.getLibraries();
            	else libs=fModel.getDebugLibraries();
            for (int i=0; i<libs.length; i++)
            {
                if (libs[i].equalsIgnoreCase(item.getText()))
                {
                    try {
                        if (!fDebug)
                            fModel.removeLibrary(i);
                        	else fModel.removeDebugLibrary(i);
                    } catch (CoreException e) {
                        SymbdevPlugin.showError(e, "Error removing library",
                                getSection().getShell());
                    }
                    return;
                }
            }
        }
    }
    
    public void addPushed()
    {
        String library=StringDialog.queryString(getSection().getShell(),
                SymbdevPlugin.MESSAGE_TITLE, "Library name", "");
        if (library==null)
            return;
        library=library.trim();
        try {
            if (!fDebug)
                fModel.addLibrary(library);
                else fModel.addDebugLibrary(library);
        }
        catch (CoreException e)
        {
            if (MMPModelException.isMMPModelException(e,
                    MMPModelException.ITEM_EXISTS))
                MessageDialog.openInformation(getSection().getShell(),
                        SymbdevPlugin.MESSAGE_TITLE, "Library already selected");
            	else SymbdevPlugin.showError(e, "Cannot add library",
            	        getSection().getShell());
        }
    }

    public void dispose() {
        fModel.removeChangeListener(IMMPModel.CHANGE_LIBRARIES, fListener);
        if (fDebug)
            fModel.removeChangeListener(IMMPModel.CHANGE_DEBUG_LIBRARIES, fDebugListener);
        super.dispose();
    }
    
    /**
     * Map libraries names into table positions
     */
    HashMap fTableLibraries=new HashMap();
    boolean fDebug;
    int fDetectedCount;
    IMMPModel fModel;
    Listener fListener;
    Listener fDebugListener;
    Table fTable;
    Button fAdd;
}
