/*
 * HumanResource.java
 *
 * Created on 27. Mai 2003, 22:19
 */

package net.sourceforge.ganttproject.resource;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.swing.DefaultListModel;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;

import net.sourceforge.ganttproject.CustomProperty;
import net.sourceforge.ganttproject.CustomPropertyDefinition;
import net.sourceforge.ganttproject.CustomPropertyHolder;
import net.sourceforge.ganttproject.CustomPropertyManager;
import net.sourceforge.ganttproject.calendar.GanttDaysOff;
import net.sourceforge.ganttproject.language.GanttLanguage;
import net.sourceforge.ganttproject.roles.Role;
import net.sourceforge.ganttproject.task.ResourceAssignment;
import java.math.BigDecimal;

/**
 * @author barmeier
 */
public class HumanResource extends ProjectResource implements CustomPropertyHolder {
    private boolean areEventsEnabled = true;
    
    private String phone = "";

    private String email = "";
    
    private String lineNumber = "" ; 
    
    private BigDecimal price = new BigDecimal(0);

    private int function;

    private Role myRole;

    private final DefaultListModel myDaysOffList = new DefaultListModel ();
    
    /* contains all the custom property values of a resource.
     * the key is the property name and the value is the property value */
    private final Map<String,Object> customFields;
    
    private final HumanResourceManager myManager;

    HumanResource(HumanResourceManager manager) {
        this.name = "";
        customFields = new HashMap();
        myManager = manager;
        // added
    }

    /** Creates a new instance of HumanResource */
    HumanResource(String name, int id, HumanResourceManager manager) {
        super(id);
        this.name = name;
        customFields = new HashMap();
        myManager = manager;
        myDaysOffList.addListDataListener(new ListDataListener() {
            public void contentsChanged(ListDataEvent e) {
                resetLoads();
            }
            public void intervalAdded(ListDataEvent e) {
                resetLoads();
            }
            public void intervalRemoved(ListDataEvent e) {
                resetLoads();
            }
        });
    }

    private HumanResource(HumanResource copy) {
        areEventsEnabled = false;
        setId(-1);
        setName(GanttLanguage.getInstance().getText("copy2")+"_"+copy.getName());
        setCostsPerUnit(copy.getCostsPerUnit());
        setDescription(copy.getDescription());
        setMaximumUnitsPerDay(copy.getMaximumUnitsPerDay());
        setUnitMeasure(copy.getUnitMeasure());
        setMail(copy.getMail());
        setPhone(copy.getPhone());
        setRole(copy.getRole());
        // Added LaboPM	
        setPrice(copy.getPrice());
        initCustomFields(copy.getCustomFields());
        myManager = copy.myManager;
        DefaultListModel copyDaysOff = copy.getDaysOff();
        for (int i=0; i<copyDaysOff.getSize(); i++) {
            myDaysOffList.addElement(copyDaysOff.get(i));
        }
        customFields = new HashMap(copy.customFields);
        areEventsEnabled = true;
    }
 
    public void delete() {
        super.delete();
        myManager.remove(this);
    }

    public HumanResourceManager getResourceManager() {
        return this.myManager;
    }
    
    public void setMail(String email) {
        if (email == null) {
            return;
        }
        this.email = email;
        fireResourceChanged();
    }

    public String getMail() {
        return email;
    }

    public void setPhone(String phone) {
        if (phone == null) {
            return;
        }
        this.phone = phone;
        fireResourceChanged();
    }

    public String getPhone() {
        return phone;
    }

    // Added LaboPM
    public void setPrice(BigDecimal price) {
        this.price = price;
        fireResourceChanged();
    }

    //  Added LaboPM
    public BigDecimal getPrice() {
        return price;
    }
    
    public void setLineNumber(String lineNumber){
        if (lineNumber == null) {
            return;
        }
        this.lineNumber = lineNumber;
        fireResourceChanged();
    }
    /** 
     * Calls the  countResNumber to get the
     * number of resources which will be set 
     * as the line Number when a resource is created.
     */
    public void setLineNumber(){   	
        this.lineNumber = countResNumber();
        fireResourceChanged();
    }

    
    public String getLineNumber() {
        return lineNumber;
    }
    
    
    
    // public void setFunction (int function) {
    // this.function=function;
    // }

    // public int getFunction () {
    // return myRole==null ? 0 : myRole.getID();
    // }

    public void setRole(Role role) {
        myRole = role;
        fireResourceChanged();
    }

    public Role getRole() {
        if (myRole == null) {
            System.err
                    .println("[HumanResource] getRole(): I have no role :( name="
                            + getName());
        }
        return myRole;
    }

    public void addDaysOff(GanttDaysOff gdo) {
        myDaysOffList.addElement(gdo);
        fireResourceChanged();
    }

    public DefaultListModel getDaysOff() {
        return myDaysOffList;
    }
    
    /* inits the customFields by the given hashtable */
    public void initCustomFields(Map source) {
        customFields.putAll(source);
    }
    
    public Map getCustomFields() {
        return customFields;
    }
    
    public boolean hasCustomFields() {
        return !customFields.isEmpty();
    }
    
    public void addCustomField(String title, Object value) {
        this.customFields.put(title,value);
    }
    
    public void removeCustomField(String title) {
        this.customFields.remove(title);
    }
    
    public Object getCustomFieldVal(String title) {
        return customFields.get(title);
    }
    
    public void setCustomFieldVal(String title, Object val) {
        this.customFields.put(title,val);
    }

    public ResourceAssignment createAssignment(ResourceAssignment assignmentToTask) {
        ResourceAssignment result = super.createAssignment(assignmentToTask);
        fireAssignmentsChanged();
        return result;
    }    
    
    public ProjectResource unpluggedClone() {
        return new HumanResource(this);
    }
    /** 
     * count the number of resources
     *
     * @return return the number of resources + 1
     * 			to start the line number at 1.
     */
    public  String countResNumber(){
        return myManager.getResources().size()+ 1 + "";
        
    }
    
    private void fireResourceChanged() {
        if (areEventsEnabled) {
            myManager.fireResourceChanged(this);
        }
    }
    
    protected void fireAssignmentsChanged() {
        if (areEventsEnabled) {
            myManager.fireAssignmentsChanged(this);
        }        
    }

    public List<CustomProperty> getCustomProperties() {
        List<CustomProperty> result = new ArrayList<CustomProperty>(customFields.size());
        for (CustomPropertyDefinition nextDefinition : myManager.getCustomPropertyManager().getDefinitions()) {
            Object nextValue = customFields.get(nextDefinition.getID());
            if (nextValue==null) {
                nextValue = nextDefinition.getDefaultValue();
            }
            result.add(new CustomPropertyImpl(nextDefinition, nextValue));
        }
        return result;
    }
    
    public CustomProperty addCustomProperty(CustomPropertyDefinition definition, String valueAsString) {
        final CustomPropertyDefinition stubDefinition = CustomPropertyManager.PropertyTypeEncoder.decodeTypeAndDefaultValue(definition.getTypeAsString(), valueAsString);
        addCustomField(definition.getID(), stubDefinition.getDefaultValue());
        return new CustomPropertyImpl(definition, stubDefinition.getDefaultValue());
    }


    private static class CustomPropertyImpl implements CustomProperty {
        private CustomPropertyDefinition myDefinition;
        private Object myValue;

        public CustomPropertyImpl(CustomPropertyDefinition definition, Object value) {
            myDefinition = definition;
            myValue = value;
        }
        public CustomPropertyDefinition getDefinition() {
            return myDefinition;
        }

        public Object getValue() {
            return myValue;
        }

        public String getValueAsString() {
            return HumanResourceManager.getValueAsString(myValue);
        }
        
    }
}
