/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
<<<<<<< Updated upstream
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
=======
 * 
 *     https://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 * See the License for the specific language governing permissions and 
>>>>>>> Stashed changes
 * limitations under the License.
 */

package org.apache.jdo.tck.models.fieldtypes;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date;
import java.util.Locale;
import java.util.Set;
import java.util.Vector;
import org.apache.jdo.tck.pc.fieldtypes.AllTypes;
import org.apache.jdo.tck.pc.fieldtypes.SimpleClass;
import org.apache.jdo.tck.pc.fieldtypes.SimpleEnum;

public class TestUtil {

  public TestUtil() {}

  // gets the value type for fields of a collection class
  public static String getFieldSpecs(String field) {
    // sample field =public Collection CollectionOfObject0
    // look for last space and get the String before the  numbers
    String valueType = "";

    int indexOfLastSpace = field.lastIndexOf(" ");
    String fieldName = field.substring(indexOfLastSpace);
    int indexOfValueType = fieldName.indexOf("Of") + 2;
    String valueTypeWithNumber = fieldName.substring(indexOfValueType);
    int lastIndexOfValueType = 0;
    for (int i = valueTypeWithNumber.length() - 1; i >= 0; i--) {
      if (Character.isDigit(valueTypeWithNumber.charAt(i))) {
        continue;
      } else {
        lastIndexOfValueType = i;
        break;
      }
    }
    valueType = valueTypeWithNumber.substring(0, lastIndexOfValueType + 1);

    return valueType;
  }

  // gets the key type and value type for fields of a Map class
  public static Vector<String> getFieldSpecsForMap(String field) {
    // sample field =public HashMap HashMapOfObject_Object0
    // fieldType -- look for the last space and get the value between Of and _
    // valueType -- look for last _ and get the String before the  numbers
    String fieldType = "";
    String valueType = "";

    int indexOfLastSpace = field.lastIndexOf(" ");
    String fieldName = field.substring(indexOfLastSpace);
    int indexOfFieldType = fieldName.indexOf("Of") + 2;
    String fieldTypeWithValueType = fieldName.substring(indexOfFieldType);
    int indexOfUnderScore = fieldTypeWithValueType.indexOf("_");
    fieldType = fieldTypeWithValueType.substring(0, indexOfUnderScore);

    String valueTypeWithNumber = fieldTypeWithValueType.substring(indexOfUnderScore + 1);
    int lastIndexOfValueType = 0;
    for (int i = valueTypeWithNumber.length() - 1; i >= 0; i--) {
      if (Character.isDigit(valueTypeWithNumber.charAt(i))) {
        continue;
      } else {
        lastIndexOfValueType = i;
        break;
      }
    }
    valueType = valueTypeWithNumber.substring(0, lastIndexOfValueType + 1);

    Vector<String> fieldSpecs = new Vector<>();
    fieldSpecs.add(fieldType);
    fieldSpecs.add(valueType);

    return fieldSpecs;
  }

  public static final String[] elementTypes =
      new String[] {
        "Object",
        "SimpleClass",
        "SimpleInterface",
        "String",
        "Date",
        "Locale",
        "BigDecimal",
        "BigInteger",
        "Byte",
        "Double",
        "Float",
        "Integer",
        "Long",
        "Short",
        "SimpleEnum"
      };

  private static int getIndexOf(String type) {
    for (int i = 0; i < elementTypes.length; i++) {
      if (type.equals(elementTypes[i])) return i;
    }
    return 9999;
  }

  @SuppressWarnings("rawtypes")
  public static Vector makeNewVectorInstance(String type, int order) {

    Vector<Object> vec = new Vector<>();

    switch (order) {
      case (1):
        switch (getIndexOf(type)) {
          case (0):
            vec.add(0, new SimpleClass(1, "Hello World"));
            vec.add(1, new SimpleClass(2, "Java Data Objects"));
            vec.add(2, new SimpleClass(2, "Java"));
            vec.add(3, new SimpleClass(4, "Origami"));
            vec.add(4, new SimpleClass(5, "watch"));
            break;
          case (1):
          case (2):
            vec.add(0, new SimpleClass(1, "Welcome"));
            vec.add(1, new SimpleClass(2, "To"));
            vec.add(2, new SimpleClass(3, "The"));
            vec.add(3, new SimpleClass(4, "Beautiful"));
            vec.add(4, new SimpleClass(5, "World"));
            break;
          case (3):
            vec.add(0, "Hello");
            vec.add(1, "Welcome");
            vec.add(2, "To The");
            vec.add(3, "Beautiful");
            vec.add(4, "World");
            break;
          case (4):
            vec.add(0, new Date(2007908));
            vec.add(1, new Date(89067382l));
            vec.add(2, new Date(890673822));
            vec.add(3, new Date(890673823));
            vec.add(4, new Date(890673824));
            break;
          case (5):
            vec.add(0, Locale.CHINA);
            vec.add(1, Locale.FRANCE);
            vec.add(2, Locale.GERMANY);
            vec.add(3, Locale.JAPAN);
            vec.add(4, Locale.ITALY);
            break;
          case (6):
            vec.add(0, new BigDecimal("2007908.54548"));
            vec.add(1, new BigDecimal("0.544"));
            vec.add(2, new BigDecimal("3002323232.545454"));
            vec.add(3, new BigDecimal("64564645656.78657"));
            vec.add(4, new BigDecimal("4564565465.2342"));
            break;
          case (7):
            vec.add(0, new BigInteger("2007908"));
            vec.add(1, new BigInteger("767575"));
            vec.add(2, new BigInteger("3002323232"));
            vec.add(3, new BigInteger("64564645656"));
            vec.add(4, new BigInteger("456445645"));
            break;
          case (8):
            vec.add(0, Byte.valueOf(Byte.MIN_VALUE));
            vec.add(1, Byte.valueOf(Byte.MAX_VALUE));
            vec.add(2, Byte.valueOf((byte) (Byte.MAX_VALUE - 20)));
            vec.add(3, Byte.valueOf((byte) (Byte.MAX_VALUE - 50)));
            vec.add(4, Byte.valueOf((byte) (Byte.MAX_VALUE - 75)));
            break;
          case (9):
            vec.add(0, Double.valueOf(AllTypes.DOUBLE_SMALLEST));
            vec.add(1, Double.valueOf(AllTypes.DOUBLE_LARGEST));
            vec.add(2, Double.valueOf(AllTypes.DOUBLE_LARGEST - 20000));
            vec.add(3, Double.valueOf(AllTypes.DOUBLE_LARGEST - 454545.436664));
            vec.add(4, Double.valueOf(AllTypes.DOUBLE_LARGEST - 2323235.76764677));
            break;
          case (10):
            vec.add(0, Float.valueOf(AllTypes.FLOAT_SMALLEST));
            vec.add(1, Float.valueOf(AllTypes.FLOAT_LARGEST));
            vec.add(2, Float.valueOf(AllTypes.FLOAT_LARGEST - 20000));
            vec.add(3, Float.valueOf((float) (AllTypes.FLOAT_LARGEST - 454545.434)));
            vec.add(4, Float.valueOf((float) (AllTypes.FLOAT_LARGEST - 565656.43434)));
            break;
          case (11):
            vec.add(0, Integer.valueOf(Integer.MIN_VALUE));
            vec.add(1, Integer.valueOf(Integer.MAX_VALUE));
            vec.add(2, Integer.valueOf(Integer.MAX_VALUE - 20000));
            vec.add(3, Integer.valueOf(Integer.MAX_VALUE - 343434343));
            vec.add(4, Integer.valueOf(Integer.MAX_VALUE - 565656));
            break;
          case (12):
            vec.add(0, Long.valueOf(Long.MIN_VALUE));
            vec.add(1, Long.valueOf(Long.MAX_VALUE));
            vec.add(2, Long.valueOf(Long.MAX_VALUE - 20000));
            vec.add(3, Long.valueOf(Long.MAX_VALUE - 343434343));
            vec.add(4, Long.valueOf(Long.MAX_VALUE - 565656));
            break;
          case (13):
            vec.add(0, Short.valueOf(Short.MIN_VALUE));
            vec.add(1, Short.valueOf(Short.MAX_VALUE));
            vec.add(2, Short.valueOf((short) (Short.MAX_VALUE - 20000)));
            vec.add(3, Short.valueOf((short) (Short.MAX_VALUE - 343)));
            vec.add(4, Short.valueOf((short) (Short.MAX_VALUE - 5656)));
            break;
          case (14):
            vec.add(0, SimpleEnum.AK);
            vec.add(1, SimpleEnum.FM);
            vec.add(2, SimpleEnum.KS);
            vec.add(3, SimpleEnum.NJ);
            vec.add(4, SimpleEnum.WI);
            break;
          default:
            throw new IndexOutOfBoundsException();
        }
        return vec;
      case (2):
        switch (getIndexOf(type)) {
          case (0):
            vec.add(0, new SimpleClass(1, "Hi There"));
            vec.add(1, new SimpleClass(1, "Hi"));
            vec.add(2, new SimpleClass(2, "Object"));
            vec.add(3, new SimpleClass(0, "Relational"));
            vec.add(4, new SimpleClass(3, "Hi There"));
            break;
          case (1):
          case (2):
            vec.add(0, new SimpleClass(1, "Peaches"));
            vec.add(1, new SimpleClass(2, "Oranges"));
            vec.add(2, new SimpleClass(3, "Blue Berries"));
            vec.add(3, new SimpleClass(4, "Apples"));
            vec.add(4, new SimpleClass(5, "Strawberries"));
            break;
          case (3):
            vec.add(0, "Peaches");
            vec.add(1, "Oranges");
            vec.add(2, "Blue Berries");
            vec.add(3, "Apples");
            vec.add(4, "Strawberries");
            break;
          case (4):
            vec.add(0, new Date(54545));
            vec.add(1, new Date(8905454l));
            vec.add(2, new Date(323545445));
            vec.add(3, new Date(890748967382l));
            vec.add(4, new Date(954545));
            break;
          case (5):
            vec.add(0, Locale.ENGLISH);
            vec.add(1, Locale.JAPANESE);
            vec.add(2, Locale.CANADA_FRENCH);
            vec.add(3, Locale.KOREA);
            vec.add(4, Locale.UK);
            break;
          case (6):
            vec.add(0, new BigDecimal("434238.5454898989"));
            vec.add(1, new BigDecimal("6.544"));
            vec.add(2, new BigDecimal("55552323232.545454"));
            vec.add(3, new BigDecimal("6456456.7543543534865785"));
            vec.add(4, new BigDecimal("456456.4353452342"));
            break;
          case (7):
            vec.add(0, new BigInteger("345345345345345345345345"));
            vec.add(1, new BigInteger("543543543543544"));
            vec.add(2, new BigInteger("65323423432423423"));
            vec.add(3, new BigInteger("87845634534543"));
            vec.add(4, new BigInteger("53452567766657567"));
            break;
          case (8):
            vec.add(0, Byte.valueOf((byte) (Byte.MAX_VALUE - 34)));
            vec.add(1, Byte.valueOf(Byte.MIN_VALUE));
            vec.add(2, Byte.valueOf((byte) (Byte.MAX_VALUE - 76)));
            vec.add(3, Byte.valueOf(Byte.MAX_VALUE));
            vec.add(4, Byte.valueOf((byte) (Byte.MAX_VALUE - 12)));
            break;
          case (9):
            vec.add(0, Double.valueOf(AllTypes.DOUBLE_LARGEST - 343434));
            vec.add(1, Double.valueOf(AllTypes.DOUBLE_SMALLEST));
            vec.add(2, Double.valueOf(AllTypes.DOUBLE_LARGEST));
            vec.add(3, Double.valueOf(AllTypes.DOUBLE_LARGEST - 65423445.436664));
            vec.add(4, Double.valueOf(AllTypes.DOUBLE_LARGEST - 7235.236764677));
            break;
          case (10):
            vec.add(0, Float.valueOf(AllTypes.FLOAT_LARGEST - 5452));
            vec.add(1, Float.valueOf(AllTypes.FLOAT_SMALLEST));
            vec.add(2, Float.valueOf((float) (AllTypes.FLOAT_LARGEST - 6564560.54)));
            vec.add(3, Float.valueOf(AllTypes.FLOAT_LARGEST));
            vec.add(4, Float.valueOf((float) (AllTypes.FLOAT_LARGEST - 9756.634)));
            break;
          case (11):
            vec.add(0, Integer.valueOf(Integer.MAX_VALUE - 54454));
            vec.add(1, Integer.valueOf(Integer.MIN_VALUE));
            vec.add(2, Integer.valueOf(Integer.MAX_VALUE));
            vec.add(3, Integer.valueOf(Integer.MAX_VALUE - 767234));
            vec.add(4, Integer.valueOf(Integer.MAX_VALUE - 23673446));
            break;
          case (12):
            vec.add(0, Long.valueOf(Long.MAX_VALUE - 545345454));
            vec.add(1, Long.valueOf(Long.MIN_VALUE));
            vec.add(2, Long.valueOf(Long.MAX_VALUE));
            vec.add(3, Long.valueOf(Long.MAX_VALUE - 3543343));
            vec.add(4, Long.valueOf(Long.MAX_VALUE - 556));
            break;
          case (13):
            vec.add(0, Short.valueOf((short) (Short.MAX_VALUE - 3434)));
            vec.add(1, Short.valueOf(Short.MIN_VALUE));
            vec.add(2, Short.valueOf(Short.MAX_VALUE));
            vec.add(3, Short.valueOf((short) (Short.MAX_VALUE - 23344)));
            vec.add(4, Short.valueOf((short) (Short.MAX_VALUE - 723)));
            break;
          case (14):
            vec.add(0, SimpleEnum.AZ);
            vec.add(1, SimpleEnum.SD);
            vec.add(2, SimpleEnum.NV);
            vec.add(3, SimpleEnum.WV);
            vec.add(4, SimpleEnum.PA);
            break;
          default:
            throw new IndexOutOfBoundsException();
        }
        return vec;
      default:
        throw new IndexOutOfBoundsException();
    }
  }

  protected static boolean containsBigDecimalKey(
      BigDecimal keyValue, Set<BigDecimal> bigDecimalKeySet) {
    for (BigDecimal nextVal : bigDecimalKeySet) {
      if (keyValue.compareTo(nextVal) == 0) {
        return true;
      }
    }
    return false;
  }

  protected static BigDecimal getBigDecimalKey(
      BigDecimal keyValue, Set<BigDecimal> bigDecimalKeySet) {
    for (BigDecimal nextVal : bigDecimalKeySet) {
      if (keyValue.compareTo(nextVal) == 0) {
        return nextVal;
      }
    }
    return null;
  }
}
