/*
 2000-2004 eBay Inc. All rights reserved.

eBay, eBay API, and eBay SDK are trademarks of eBay Inc.

Sample Source Code License
The material below is sample source code in the form of example
applications and code fragments (both in the source code files and
documentation provided hereunder), and may include a tutorial
application (collectively, "Sample Source Code" or "SSC").  YOUR
RECEIPT AND USE OF THE SSC IS CONTINGENT UPON THE TERMS AND CONDITIONS
SET FORTH BELOW.

License. Subject to the terms and restrictions set forth herein, eBay
grants you a non-exclusive, non-transferable, non-sublicensable,
royalty-free license to download and use the SSC solely to create and
distribute derivative works ("Derivative Works") which are designed to
assist your end users to efficiently interact with the eBay Site
(e.g., a listing application) (the "License").  Except as otherwise
expressly stated below, you are not permitted to sell, lease, rent,
copy, distribute or sublicense the SSC, or derivative copies thereof,
or to use it in a time-sharing arrangement or in any other
unauthorized manner. This License does not grant you any rights to
patents, copyrights, trade secrets, trademarks, or any other rights in
respect to the SSC.

Redistribution. You may not use the SSC in any manner that is not
expressly authorized under this License. Without limiting the
foregoing, you may redistribute, use and create Derivative Works in
source and binary forms, subject to the following conditions:
  1. Redistributions of SSC must retain this list of conditions and
     the copyright notice and disclaimer noted below.
  2. Redistributions in binary form must reproduce the copyright
     notice, this list of conditions and the disclaimer in the
     documentation and/or other materials provided with the
     distribution.
  3. Redistribution Conditions:
      Neither the name of eBay Inc. nor the names of its contributors
       may be used to endorse or promote products derived from this
       software or materials without specific prior written
       permission.
      Disclaimer. "THIS SOFTWARE AND ANY RELATED MATERIALS ARE
       PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
       ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
       COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
       INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
       DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
       LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
       (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
       THE USE OF THIS SOFTWARE, AND/OR ANY RELATED MATERIALS, EVEN IF
       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
      Copyright Notice: "Copyright (c) 2003, eBay Inc.
                          All rights reserved."

*/

package com.ebay.sdk.attributes;

import java.util.Hashtable;
import java.util.ArrayList;
import java.util.Enumeration;
import com.ebay.sdk.attributes.model.*;
import com.ebay.sdk.SdkException;

/**
 *
 * <p>Title: AttributesLib for Java</p>
 * <p>Description: </p>
 * <p>Copyright: Copyright (c) 2004</p>
 * <p>Company: eBay Inc.</p>
 * @author Weijun Li
 * @version 1.0
 */
class AttrInfo
{
  /**
   * See AttributType
   */
  public int typeId;

  public String csid;

  public String attrId;

  public String[] val;
}

/**
 *
 * <p>Title: AttributesLib for Java</p>
 * <p>Description: </p>
 * <p>Copyright: Copyright (c) 2004</p>
 * <p>Company: eBay Inc.</p>
 * @author Weijun Li
 * @version 1.0
 */
abstract class AttrParamParser
{
  public static final String ATTR = "attr";
  public static final String ATTR_D = "attr_d";
  public static final String ATTR_T = "attr_t";

  public static final String US = "_";
  public static final String USC = "_c";
  public static final String USD = "_d";
  public static final String USM = "_m";
  public static final String UST = "_t";
  public static final String USY = "_y";

  public static final String SEP = ",";
  public static String SEPS = ",";

  /**
   *
   * @param vcsid int
   * @param request Map
   * @return AttributeSet
   */
  public static AttributeSet parse(int vcsid, java.util.Map request)
  {
    int index;
    Hashtable htAttr = new Hashtable();

    String csidStr = new Integer(vcsid).toString();

    Object[] keys = request.keySet().toArray();
    for(int i = 0; i < keys.length; i++ )
    {
      String key = (String)keys[i];
    //foreach (string key in request.AllKeys)
    //{
      if( !(key.startsWith(ATTR + csidStr) ||
              key.startsWith(ATTR_D + csidStr) ||
              key.startsWith(ATTR_T + csidStr))
              )
        continue;

      int type = AttributeTypes.ATTR_ID;

      String[] val = (String[])request.get(key);
      String skey = key.substring(ATTR.length());
      if (skey.startsWith(USD))
      {
        index = skey.lastIndexOf(US);
        String ekey = skey.substring(index);
        skey = skey.substring(0, index);
        skey = skey.substring(USD.length());
        if (USC.equals(ekey))
        {
          type = AttributeTypes.ATTR_TEXT;
        }
        else if (USD.equals(ekey))
        {
          type = AttributeTypes.ATTR_DATE_D;
        }
        else if (USM.equals(ekey))
        {
          type = AttributeTypes.ATTR_DATE_M;
        }
        else if (USY.equals(ekey))
        {
          type = AttributeTypes.ATTR_DATE_Y;
        }
      }
      else if (skey.startsWith(UST))
      {
          skey = skey.substring(UST.length());
          type = AttributeTypes.ATTR_TEXT;
      }
      else
      {
        if (val.length > 1)
        {
          type = AttributeTypes.ATTR_IDS;
        }
        else
        {
          type = AttributeTypes.ATTR_ID;
        }
      }

      AttrInfo info = new AttrInfo();
      info.typeId = type;

      // Peel of the vcsid
      index = skey.indexOf(US);
      info.attrId = skey.substring(index + 1);
      info.csid = skey.substring(0, index);
      info.val = (String[])request.get(key);
      skey = info.attrId;

      Object obj = htAttr.get(info.attrId);
      if (obj != null)
      {
        if (obj instanceof ArrayList)
        {
          ((ArrayList)obj).add(info);
        }
        else
        {
          ArrayList al = new ArrayList();
          al.add(obj);
          al.add(info);
          htAttr.remove(info.attrId);
          htAttr.put(skey, al);
        }
      }
      else
      {
        htAttr.put(info.attrId, info);
      }
    }

    return compile(htAttr, vcsid);
  }

  static void ArrayList_removeRange(ArrayList al, int index, int count)
  {
    for(int i = 0; i < count; i++ )
    {
      al.remove(index + i);
    }
  }

  private static AttributeSet compile(Hashtable ht, int vcsid)
  {
    AttributeSet attrSet = new AttributeSet();
    attrSet.setAttributeSetID(vcsid);

    int cnt = ht.size();
    Enumeration iter = ht.keys();

    String key;
    Object val;
    AttrInfo info;
    ArrayList al;
    Attribute attr = null;

    while(iter.hasMoreElements())
    {
      key = iter.nextElement().toString();
      val = ht.get(key);
      if (val instanceof ArrayList)
      {
        al = (ArrayList)val;
        cnt = al.size();
        // Option Other
        if (cnt == 2)
        {
          AttrInfo info0 = (AttrInfo)al.get(0);
          AttrInfo info1 = (AttrInfo)al.get(1);
          if (info0.typeId == AttributeTypes.ATTR_ID)
          {
            attr = ExtractAttr2(info0, info1);
            attrSet.add(attr);
          }
          else if (info1.typeId == AttributeTypes.ATTR_ID)
          {
            attr = ExtractAttr2(info1, info0);
            attrSet.add(attr);
          }
          else
          {
            //Unknow type.
          }
        }
        // DateTime
        else if (cnt == 3)
        {
          YMD ymd = new YMD(null, null, null);
          for (int i = 0; i < cnt; i ++)
          {
            info = (AttrInfo)al.get(i);
            switch(info.typeId)
            {
              case AttributeTypes.ATTR_DATE_D:
                ymd.day = info.val[0];
                break;
              case AttributeTypes.ATTR_DATE_M:
                ymd.month = info.val[0];
                break;
              case AttributeTypes.ATTR_DATE_Y:
                ymd.year = info.val[0];
                break;
            }
          }

          YMD.FixYMD(ymd);

          if (ymd.day != null && ymd.month!= null && ymd.year != null)
          {
            info = (AttrInfo)al.get(0);
            ArrayList_removeRange(al, 0, cnt);

            info.typeId = AttributeTypes.ATTR_TEXT_DATE;
            info.val = new String[] { ymd.year + ymd.month + ymd.day };
            al.add(info);

            attr = ExtractAttr(info);
            ((Value)attr.getValue()[0]).setValueID(new Integer(ValueIds.COMPLETE_TEXT_DATE));
            //attr.ValueList[0].ValueId = (int)ValueIds.COMPLETE_TEXT_DATE;

            attrSet.add(attr);
          }
        }
      }
      else
      {
        info = (AttrInfo) val;

        // Only year field.
        if( info.typeId == AttributeTypes.ATTR_DATE_Y )
        {
          YMD ymd = new YMD(info.val[0], "1", "1");
          YMD.FixYMD(ymd);

          info.typeId = AttributeTypes.ATTR_TEXT_DATE;
          info.val = new String[] { ymd.year + ymd.month + ymd.day };

          attr = ExtractAttr(info);
          ((Value)attr.getValue()[0]).setValueID(new Integer(ValueIds.COMPLETE_TEXT_DATE));
          //attr.ValueList[0].ValueId = (int)ValueIds.COMPLETE_TEXT_DATE;

          attrSet.add(attr);
        }
        else
        {
          attr = ExtractAttr(info);
          if( attr.getType() == AttributeTypes.ATTR_TEXT )
          {
            ((Value)attr.getValue()[0]).setValueID(new Integer(ValueIds.TEXT));
            //attr.ValueList[0].ValueId = (int) ValueIds.TEXT;
          }

          attrSet.add(attr);
        }
      }
    }

    return attrSet;
  }

  private static int AttrToValType(int attrType)
  {
    if( attrType == AttributeTypes.ATTR_ID || attrType == AttributeTypes.ATTR_IDS )
      return ValueTypes.ValueId;
    else
      return ValueTypes.Text;
  }

  private static com.ebay.sdk.attributes.model.Attribute ExtractAttr(AttrInfo info)
  {
    Value val = null;
    com.ebay.sdk.attributes.model.Attribute attr = new com.ebay.sdk.attributes.model.Attribute();
    attr.setAttributeID(Integer.parseInt(info.attrId));
    attr.setType(info.typeId);

    //IValueList list = new ValueList();
    //attr.ValueList = list;

    int valType = AttrToValType(info.typeId);

    if (info.typeId == AttributeTypes.ATTR_ID)
    {
      val = new Value(valType);
      val.setValueID(new Integer(info.val[0]));
      attr.addValue(val);
      /*
      if (info.val.equals"-10"))
      {
              attr.SType = -1;
      }
      */
    }
    else if (info.typeId == AttributeTypes.ATTR_IDS)
    {
      for (int i = 0; i < info.val.length; i++)
      {
        val = new Value(valType);
        val.setValueID(new Integer(info.val[i]));
        attr.addValue(val);
      }
      /*
      if (info.val.indexOf("-10") > -1)
      {
              attr.SType = -1;
      }
      */
    }
    else
    {
      val = new Value(valType);
      val.setValueLiteral(info.val[0]);
      attr.addValue(val);
    }

    return attr;
  }

  private static com.ebay.sdk.attributes.model.Attribute ExtractAttr2(AttrInfo info1, AttrInfo info2)
  {
    com.ebay.sdk.attributes.model.Attribute attr = new com.ebay.sdk.attributes.model.Attribute();
    //IValueList list = new ValueList();
    //attr.ValueList = list;
    attr.setAttributeID(Integer.parseInt(info1.attrId));
    attr.setType(info1.typeId);

    Value val = new Value();
    val.setValueID(new Integer(info1.val[0]));
    val.setValueLiteral(info2.val[0]);

    attr.addValue(val);

    return attr;
  }

  private static com.ebay.sdk.attributes.model.Attribute ExtractAttr(AttrInfo [] infos)
  {
    Value val = null;
    com.ebay.sdk.attributes.model.Attribute attr = new com.ebay.sdk.attributes.model.Attribute();
    attr.setAttributeID(Integer.parseInt(infos[0].attrId));
    //IValueList list = new ValueList();
    //attr.ValueList = list;

    AttrInfo info;
    int cnt = infos.length;
    for (int i = 0; i < cnt; i ++)
    {
      info = infos[i];
      if (info.typeId == AttributeTypes.ATTR_ID)
      {
        val = new Value();
        val.setValueID(new Integer(info.val[0]));
        attr.addValue(val);
      }
      else if (info.typeId == AttributeTypes.ATTR_IDS)
      {
        for (int j = 0; j < info.val.length; j++)
        {
          val = new Value();
          val.setValueID(new Integer(info.val[j]));
          attr.addValue(val);
        }
      }
      else
      {
        val = new Value();
        val.setValueLiteral(info.val[0]);
        attr.addValue(val);
      }
    }

    return attr;
  }
}
