//-------------------------------------------------------------------------------------------------
// Module    : $RCSfile: UsabilityDefectDescriptions.java,v $
// Version   : $Revision: 0.0 $  $Author: pharms $  $Date: 18.07.2012 $
// Project   : UsabilityEvaluationManager
// Creation  : 2012 by pharms
// Copyright : Patrick Harms, 2012
//-------------------------------------------------------------------------------------------------
package de.ugoe.cs.quest.usability;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Unmarshaller;

//-------------------------------------------------------------------------------------------------
/**
 * TODO comment
 * 
 * @version $Revision: $ $Date: 18.07.2012$
 * @author 2012, last modified by $Author: pharms$
 */
//-------------------------------------------------------------------------------------------------
public enum UsabilityDefectDescription
{
  TEXT_FIELD_INPUT_RATIO,
  TEXT_FIELD_INPUT_REPETITIONS,
  TEXT_FIELD_NO_LETTER_OR_DIGIT_RATIO;

  /** */
  private static final String DEFAULT_MESSAGES_FILE = "defectDescriptions_en.xml";
  
  /** */
  private static DefectDescriptions sDefectDescriptions;

  /** */
  private DefectDescription mDefectDescription;
  
  //-----------------------------------------------------------------------------------------------
  /**
   * TODO: comment
   *
   * @param name
   * @param ordinal
   */
  //-----------------------------------------------------------------------------------------------
  private UsabilityDefectDescription()
  {
    init();
  }

  //-----------------------------------------------------------------------------------------------
  /**
   * TODO: comment
   *
   */
  //-----------------------------------------------------------------------------------------------
  @SuppressWarnings("unchecked")
  private void init()
  {
    synchronized (this.getClass())
    {
      if (sDefectDescriptions == null)
      {
        InputStream inputStream = ClassLoader.getSystemResourceAsStream(DEFAULT_MESSAGES_FILE);

        try
        {
          String packageName = DefectDescriptions.class.getPackage().getName();
          JAXBContext jaxbContext = JAXBContext.newInstance(packageName);
          Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
        
          sDefectDescriptions =
            ((JAXBElement<DefectDescriptions>) unmarshaller.unmarshal(inputStream)).getValue();
        }
        catch (Exception e)
        {
          throw new RuntimeException("error while initializing usability defect descriptions", e);
        }
        finally
        {
          if (inputStream != null)
          {
            try
            {
              inputStream.close();
            }
            catch (IOException e)
            {
              // ignore
            }
          }
        }
      }
    }
    
    for (DefectDescription description : sDefectDescriptions.getDefectDescription())
    {
      if (this.name().equals(description.getDefectId()))
      {
        mDefectDescription = description;
        break;
      }
    }
    
    if (mDefectDescription == null)
    {
      throw new RuntimeException("error while initializing usability defect descriptions. No " +
                                 "description text available for description " + this.name());
    }
  }

  //-----------------------------------------------------------------------------------------------
  /**
   * 
   */
  //-----------------------------------------------------------------------------------------------
  public String[] getDescriptionParameters()
  {
    List<String> parameters = new ArrayList<String>();
    
    for (Object fragment : mDefectDescription.getTextFragmentOrParameterFragment())
    {
      if (fragment instanceof ParameterFragment)
      {
        parameters.add(((ParameterFragment) fragment).getParameterName());
      }
    }
    
    return parameters.toArray(new String[parameters.size()]);
  }
  
  //-----------------------------------------------------------------------------------------------
  /**
   * 
   */
  //-----------------------------------------------------------------------------------------------
  public String toString(Map<String, String> parameters) throws IllegalArgumentException
  {
    StringBuffer result = new StringBuffer();
    
    for (Object fragment : mDefectDescription.getTextFragmentOrParameterFragment())
    {
      if (result.length() > 0)
      {
        result.append(" ");
      }
      
      if (fragment instanceof ParameterFragment)
      {
        String value = null;
        if (parameters != null)
        {
          value = parameters.get(((ParameterFragment) fragment).getParameterName());
        }
        
        if (value != null)
        {
          result.append(value);
        }
        else
        {
          throw new IllegalArgumentException
            ("required parameter \"" + ((ParameterFragment) fragment).getParameterName() +
             "\" for usability defect description " + this.name() + " not provided");
        }
      }
      else
      {
        result.append(getFragmentString(fragment));
      }
    }
    
    return result.toString();
  }

  //-----------------------------------------------------------------------------------------------
  /* (non-Javadoc)
   * @see java.lang.Enum#toString()
   */
  //-----------------------------------------------------------------------------------------------
  @Override
  public String toString()
  {
    StringBuffer result = new StringBuffer();
    
    int paramCount = 1;
    for (Object fragment : mDefectDescription.getTextFragmentOrParameterFragment())
    {
      if (result.length() > 0)
      {
        result.append(" ");
      }
      
      if (fragment instanceof ParameterFragment)
      {
        result.append("<parameter");
        result.append(paramCount++);
        result.append(">");
      }
      else
      {
        result.append(getFragmentString(fragment));
      }
    }
    
    return result.toString();
  }

  //-----------------------------------------------------------------------------------------------
  /**
   * TODO: comment
   *
   * @param fragment
   * @return
   */
  //-----------------------------------------------------------------------------------------------
  private String getFragmentString(Object fragment)
  {
    String fragmentStr = fragment.toString().trim();
    
    fragmentStr = fragmentStr.replaceAll("\n", " ");
    
    while (fragmentStr.indexOf("  ") > -1)
    {
      fragmentStr = fragmentStr.replaceAll("  ", " ");
    }
    
    return fragmentStr;
  }

}
