/*******************************************************************************
 * 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
 *
 * 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 limitations
 * under the License.
 *******************************************************************************/
package org.apache.ofbiz.datafile;

import java.io.Serializable;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;

import org.apache.ofbiz.base.crypto.HashCrypt;
import org.apache.ofbiz.base.util.UtilValidate;
import org.apache.ofbiz.common.login.LoginServices;

/**
 * Record
 */
@SuppressWarnings("serial")
public class Record implements Serializable {

    /** Contains a map with field data by name */
    protected Map<String, Object> fields;

    /** Contains the name of the record definition */
    protected String recordName;

    /** Contains the definition for the record */
    protected transient ModelRecord modelRecord;

    protected Record parentRecord = null;
    protected List<Record> childRecords = new ArrayList<Record>();

    /** Creates new Record */
    protected Record(ModelRecord modelRecord) {
    if (modelRecord == null)
        throw new IllegalArgumentException("Cannont create a Record with a null modelRecord parameter");
    this.recordName = modelRecord.name;
    this.modelRecord = modelRecord;
    this.fields = new HashMap<String, Object>();
    }

    /** Creates new Record from existing Map */
    protected Record(ModelRecord modelRecord, Map<String, Object> fields) {
    if (modelRecord == null)
        throw new IllegalArgumentException("Cannont create a Record with a null modelRecord parameter");
    this.recordName = modelRecord.name;
    this.modelRecord = modelRecord;
    this.fields = (fields == null ? new HashMap<String, Object>() : new HashMap<String, Object>(fields));
    }

    public String getRecordName() {
    return recordName;
    }

    public ModelRecord getModelRecord() {
    if (modelRecord == null) {
        throw new IllegalStateException("[Record.getModelRecord] could not find modelRecord for recordName " + recordName);
    }
    return modelRecord;
    }

    public Object get(String name) {
    if (getModelRecord().getModelField(name) == null) {
        throw new IllegalArgumentException("[Record.get] \"" + name + "\" is not a field of " + recordName);
        // Debug.logWarning("[GenericRecord.get] \"" + name + "\" is not a field of " + recordName + ", but getting anyway...", module);
    }
    return fields.get(name);
    }

    public String getString(String name) {
    Object object = get(name);

    if (object == null)
        return null;
    if (object instanceof java.lang.String)
        return (String) object;
    else
        return object.toString();
    }

    public String getStringAndEmpty(String name) {
    Object object = get(name);

    if (object == null)
        return "";
    if (object instanceof java.lang.String)
        return (String) object;
    else
        return object.toString();
    }

    public java.sql.Timestamp getTimestamp(String name) {
    return (java.sql.Timestamp) get(name);
    }

    public java.sql.Time getTime(String name) {
    return (java.sql.Time) get(name);
    }

    public java.sql.Date getDate(String name) {
    return (java.sql.Date) get(name);
    }

    public Integer getInteger(String name) {
    return (Integer) get(name);
    }

    public Long getLong(String name) {
    return (Long) get(name);
    }

    public Float getFloat(String name) {
    return (Float) get(name);
    }

    public Double getDouble(String name) {
    return (Double) get(name);
    }

    /** Sets the named field to the passed value, even if the value is null
     * @param name The field name to set
     * @param value The value to set
     */
    public void set(String name, Object value) {
    set(name, value, true);
    }

    /** Sets the named field to the passed value. If value is null, it is only
     *  set if the setIfNull parameter is true.
     * @param name The field name to set
     * @param value The value to set
     * @param setIfNull Specifies whether or not to set the value if it is null
     */
    public synchronized void set(String name, Object value, boolean setIfNull) {
    if (getModelRecord().getModelField(name) == null) {
        throw new IllegalArgumentException("[Record.set] \"" + name + "\" is not a field of " + recordName);
        // Debug.logWarning("[GenericRecord.set] \"" + name + "\" is not a field of " + recordName + ", but setting anyway...", module);
    }
    if (value != null || setIfNull) {
        if (value instanceof Boolean) {
        value = ((Boolean) value).booleanValue() ? "Y" : "N";
        }
        fields.put(name, value);
    }
    }

    /**
     * little endian reader for 2 byte short.
     */
    public final short readLEShort(byte[] byteArray) {
    return  (short)(
        (byteArray[1]&0xff) << 8 |
        (byteArray[0]&0xff));

    }

    /**
     * little endian reader for 4 byte int.
     */
    public final int readLEInt(byte []byteArray) {
    return
    (byteArray[3])      << 24 |
    (byteArray[2]&0xff) << 16 |
    (byteArray[1]&0xff) <<  8 |
    (byteArray[0]&0xff);
    }

    /**
     * little endian reader for 8 byte long.
     */
    public final long readLELong(byte []byteArray) {
    return
    (long)(byteArray[7])      << 56 |  /* long cast needed or shift done modulo 32 */
    (long)(byteArray[6]&0xff) << 48 |
    (long)(byteArray[5]&0xff) << 40 |
    (long)(byteArray[4]&0xff) << 32 |
    (long)(byteArray[3]&0xff) << 24 |
    (long)(byteArray[2]&0xff) << 16 |
    (long)(byteArray[1]&0xff) <<  8 |
    (byteArray[0]&0xff);
    }

    /** Sets the named field to the passed value, converting the value from a String to the current type using <code>Type.valueOf()</code>
     * @param name The field name to set
     * @param value The String value to convert and set
     */
    public void setString(String name, String value) throws ParseException {
    if (name == null || value == null || value.equals(""))
        return;
    ModelField field = getModelRecord().getModelField(name);

    if (field == null)
        set(name, value); // this will get an error in the set() method...

    // if the string is all spaces ignore
    boolean nonSpace = false;

    for (int i = 0; i < value.length(); i++) {
        if (value.charAt(i) != ' ') {
        nonSpace = true;
        break;
        }
    }
    if (!nonSpace)
        return;

    // if (Debug.verboseOn()) Debug.logVerbose("Value: " + value, module);

    String fieldType = field.type;

    // first the custom types that need to be parsed
    if (fieldType.equals("CustomTimestamp")) {
        // this custom type will take a string a parse according to date formatting
        // string then put the result in a java.sql.Timestamp
        // a common timestamp format for flat files is with no separators: yyyyMMddHHmmss
        SimpleDateFormat sdf = new SimpleDateFormat(field.format);
        java.util.Date tempDate = sdf.parse(value);
        java.sql.Timestamp timestamp = new java.sql.Timestamp(tempDate.getTime());

        set(name, timestamp);
    } else if (fieldType.equals("CustomDate")) {
        // a common date only format for flat files is with no separators: yyyyMMdd or MMddyyyy
        SimpleDateFormat sdf = new SimpleDateFormat(field.format);
        java.util.Date tempDate = sdf.parse(value);
        java.sql.Date date = new java.sql.Date(tempDate.getTime());

        set(name, date);
    } else if (fieldType.equals("CustomTime")) {
        // a common time only format for flat files is with no separators: HHmmss
        SimpleDateFormat sdf = new SimpleDateFormat(field.format);
        java.util.Date tempDate = sdf.parse(value);
        java.sql.Time time = new java.sql.Time(tempDate.getTime());

        set(name, time);
    } else if (fieldType.equals("FixedPointDouble")) {
        // this custom type will parse a fixed point number according to the number
        // of decimal places in the formatting string then place it in a Double
        NumberFormat nf = NumberFormat.getNumberInstance();
        Number tempNum = nf.parse(value);
        double number = tempNum.doubleValue();
        double decimalPlaces = Double.parseDouble(field.format);
        double divisor = Math.pow(10.0, decimalPlaces);

        number = number / divisor;
        set(name, Double.valueOf(number));
    } // standard types
    else if (fieldType.equals("java.lang.String") || fieldType.equals("String"))
        if (field.format.equals("EncryptedString")) {
        String hashType = LoginServices.getHashType();
        set(name, HashCrypt.digestHash(hashType, value.getBytes()));
        } else {
        set(name, value);
        }
    else if (fieldType.equals("NullTerminatedString")) {
        int terminate = value.indexOf(0x0);
        set(name, terminate>0?value.substring(0,terminate):value);
    } else if (fieldType.equals("java.sql.Timestamp") || fieldType.equals("Timestamp"))
        set(name, java.sql.Timestamp.valueOf(value));
    else if (fieldType.equals("java.sql.Time") || fieldType.equals("Time"))
        set(name, java.sql.Time.valueOf(value));
    else if (fieldType.equals("java.sql.Date") || fieldType.equals("Date"))
        set(name, java.sql.Date.valueOf(value));
    else if (fieldType.equals("java.lang.Integer") || fieldType.equals("Integer"))
        set(name, Integer.valueOf(value));
    else if (fieldType.equals("java.lang.Long") || fieldType.equals("Long"))
        set(name, Long.valueOf(value));
    else if (fieldType.equals("java.lang.Float") || fieldType.equals("Float"))
        set(name, Float.valueOf(value));
    else if (fieldType.equals("java.lang.Double") || fieldType.equals("Double"))
        set(name, Double.valueOf(value));
    else if (fieldType.equals("LEShort"))
        set(name, Short.valueOf(readLEShort(value.getBytes())));
    else if (fieldType.equals("LEInteger"))
        set(name, Integer.valueOf(readLEInt(value.getBytes())));
    else if (fieldType.equals("LELong"))
        set(name, Long.valueOf(readLELong(value.getBytes())));
    else {
        throw new IllegalArgumentException("Field type " + fieldType + " not currently supported. Sorry.");
    }
    }

    public String getFixedString(String name) {
    if (name == null)
        return null;
    if (getModelRecord() == null)
        throw new IllegalArgumentException("Could not find modelrecord for field named \"" + name + "\"");
    ModelField field = getModelRecord().getModelField(name);

    if (field == null)
        throw new IllegalArgumentException("Could not find model for field named \"" + name + "\"");

    Object value = get(name);

    if (value == null) {
        return null;
    }

    String fieldType = field.type;
    String str = null;

    // first the custom types that need to be parsed
    if (fieldType.equals("CustomTimestamp")) {
        // a common timestamp format for flat files is with no separators: yyyyMMddHHmmss
        SimpleDateFormat sdf = new SimpleDateFormat(field.format);
        java.sql.Timestamp timestamp = (java.sql.Timestamp) value;

        str = sdf.format(new Date(timestamp.getTime()));
    } else if (fieldType.equals("CustomDate")) {
        // a common date only format for flat files is with no separators: yyyyMMdd or MMddyyyy
        SimpleDateFormat sdf = new SimpleDateFormat(field.format);
        java.sql.Date date = (java.sql.Date) value;

        str = sdf.format(new Date(date.getTime()));
    } else if (fieldType.equals("CustomTime")) {
        // a common time only format for flat files is with no separators: HHmmss
        SimpleDateFormat sdf = new SimpleDateFormat(field.format);
        java.sql.Time time = (java.sql.Time) value;

        str = sdf.format(new Date(time.getTime()));
    } else if (fieldType.equals("FixedPointDouble")) {
        // this custom type will parse a fixed point number according to the number
        // of decimal places in the formatting string then place it in a Double
        double decimalPlaces = Double.parseDouble(field.format);
        double multiplier = Math.pow(10.0, decimalPlaces);
        double dnum = multiplier * ((Double) value).doubleValue();
        long number = Math.round(dnum);

        str = padFrontZeros(Long.toString(number), field.length);
        // if (Debug.infoOn()) Debug.logInfo("[Record.getFixedString] FixedPointDouble: multiplier=" + multiplier + ", value=" + value + ", dnum=" + dnum + ", number=" + number + ", str=" + str, module);
    } // standard types
    else if (fieldType.equals("java.lang.String") || fieldType.equals("String"))
        str = value.toString();
    else if (fieldType.equals("java.sql.Timestamp") || fieldType.equals("Timestamp"))
        str = value.toString();
    else if (fieldType.equals("java.sql.Time") || fieldType.equals("Time"))
        str = value.toString();
    else if (fieldType.equals("java.sql.Date") || fieldType.equals("Date"))
        str = value.toString();
    // for all numbers, pad front with zeros if field length is specified
    else if (fieldType.equals("java.lang.Integer") || fieldType.equals("Integer"))
        str = padFrontZeros(value.toString(), field.length);
    else if (fieldType.equals("java.lang.Long") || fieldType.equals("Long"))
        str = padFrontZeros(value.toString(), field.length);
    else if (fieldType.equals("java.lang.Float") || fieldType.equals("Float"))
        str = padFrontZeros(value.toString(), field.length);
    else if (fieldType.equals("java.lang.Double") || fieldType.equals("Double"))
        str = padFrontZeros(value.toString(), field.length);
    else {
        throw new IllegalArgumentException("Field type " + fieldType + " not currently supported. Sorry.");
    }

    if (str != null && field.length > 0 && str.length() < field.length) {
        // pad the end with spaces
        StringBuilder strBuf = new StringBuilder(str);

        while (strBuf.length() < field.length)
        strBuf.append(' ');
        str = strBuf.toString();
    }
    return str;
    }

    public String writeLineString(ModelDataFile modelDataFile) throws DataFileException {
    ModelRecord modelRecord = getModelRecord();
    boolean isFixedRecord = ModelDataFile.SEP_FIXED_RECORD.equals(modelDataFile.separatorStyle);
    boolean isFixedLength = ModelDataFile.SEP_FIXED_LENGTH.equals(modelDataFile.separatorStyle);
    boolean isDelimited = ModelDataFile.SEP_DELIMITED.equals(modelDataFile.separatorStyle);

    StringBuilder lineBuf = new StringBuilder();

    for (ModelField modelField: modelRecord.fields) {
        String data = this.getFixedString(modelField.name);

        if (isDelimited && null != modelDataFile.textDelimiter) {
        lineBuf.append(modelDataFile.textDelimiter);
        }

        // if field is null (not set) then assume we want to pad the field
        char PAD_CHAR = ' ';

        if (data == null) {
        StringBuilder sb = new StringBuilder("");

        for (int i = 0; i < modelField.length; i++)
            sb.append(PAD_CHAR);
        data = sb.toString();
        }

        // Pad the record
        if (isFixedRecord) {
        while (modelField.position > lineBuf.length())
            lineBuf.append(" ");
        }
        // if (Debug.infoOn()) Debug.logInfo("Field: " + modelField.name + " Position: " + modelField.position + " BufLen: " + lineBuf.length(), module);

        // if (Debug.infoOn()) Debug.logInfo("Got data \"" + data + "\" for field " + modelField.name + " in record " + modelRecord.name, module);
        if (modelField.length > 0 && data.length() != modelField.length)
        throw new DataFileException("Got field length " + data.length() + " but expected field length is " + modelField.length + " for field \"" +
            modelField.name + "\" of record \"" + modelRecord.name + "\" data is: \"" + data + "\"");

        lineBuf.append(data);
        if (isDelimited) {
        if (null != modelDataFile.textDelimiter) {
            lineBuf.append(modelDataFile.textDelimiter);
        }
        lineBuf.append(modelDataFile.delimiter);
        }
    }

    if (isDelimited) {
        // just remove the last delimiter to finish clean, otherwise shows as extra column
        lineBuf.setLength(lineBuf.length() - 1);
    }

    if ((isFixedRecord || isFixedLength) && modelDataFile.recordLength > 0 && lineBuf.length() != modelDataFile.recordLength)
        throw new DataFileException("Got record length " + lineBuf.length() + " but expected record length is " + modelDataFile.recordLength +
            " for record \"" + modelRecord.name + "\" data line is: \"" + lineBuf + "\"");

    // for convenience, insert the type-code in where it is looked for, if exists
    if (modelRecord.tcPosition > 0 && modelRecord.typeCode.length() > 0) {
        lineBuf.replace(modelRecord.tcPosition, modelRecord.tcPosition + modelRecord.tcLength, modelRecord.typeCode);
    }

    if (isFixedLength || isDelimited)
        lineBuf.append('\n');

    return lineBuf.toString();
    }

    String padFrontZeros(String str, int totalLength) {
    if (totalLength > 0 && str.length() < totalLength) {
        // pad the front with zeros
        StringBuilder zeros = new StringBuilder();
        int numZeros = totalLength - str.length();

        for (int i = 0; i < numZeros; i++)
        zeros.append('0');
        zeros.append(str);
        return zeros.toString();
    } else
        return str;
    }

    public Record getParentRecord() {
    return parentRecord;
    }

    public List<Record> getChildRecords() {
    return childRecords;
    }

    public void addChildRecord(Record record) {
    childRecords.add(record);
    }

    /** Creates new Record
     * @param modelRecord
     * @throws DataFileException Exception thown for various errors, generally has a nested exception
     * @return return the Record Object created
     */
    public static Record createRecord(ModelRecord modelRecord) throws DataFileException {
    Record record = new Record(modelRecord);

    return record;
    }

    /** Creates new Record from existing fields Map
     * @param modelRecord
     * @param fields
     * @throws DataFileException Exception thown for various errors, generally has a nested exception
     * @return return the Record Object created
     */
    public static Record createRecord(ModelRecord modelRecord, Map<String, Object> fields) throws DataFileException {
    Record record = new Record(modelRecord, fields);

    return record;
    }

    /**
     * @param line
     * @param lineNum
     * @param modelRecord
     * @throws DataFileException Exception thown for various errors, generally has a nested exception
     * @return return the Record Object created
     */
    public static Record createRecord(String line, int lineNum, ModelRecord modelRecord) throws DataFileException {
    Record record = new Record(modelRecord);

    for (ModelField modelField: modelRecord.fields) {
        String strVal = null;


        try {
        strVal = line.substring(modelField.position, modelField.position + modelField.length);
        } catch (IndexOutOfBoundsException ioobe) {
        throw new DataFileException("Field " + modelField.name + " from " + modelField.position +
            " for " + modelField.length + " chars could not be read from a line (" + lineNum + ") with only " +
            line.length() + " chars.", ioobe);
        }
        try {
        record.setString(modelField.name, strVal);
        } catch (java.text.ParseException e) {
        throw new DataFileException("Could not parse field " + modelField.name + ", format string \"" + modelField.format + "\" with value " + strVal +
            " on line " + lineNum, e);
        } catch (java.lang.NumberFormatException e) {
        throw new DataFileException("Number not valid for field " + modelField.name + ", format string \"" + modelField.format + "\" with value " +
            strVal + " on line " + lineNum, e);
        }
    }
    return record;
    }

    /**
     * @param line
     * @param lineNum
     * @param modelRecord
     * @param delimiter
     * @throws DataFileException Exception thown for various errors, generally has a nested exception
     * @return return a Record Object
     */
    public static Record createDelimitedRecord(String line, int lineNum, ModelRecord modelRecord, char delimiter, String textDelimiter) throws DataFileException {
    Record record = new Record(modelRecord);

    StringTokenizer st = null;
    if (line.endsWith(String.valueOf(delimiter))) {
        st = new StringTokenizer(line + " ", "" + delimiter, true);
    }
    else {
        st = new StringTokenizer(line, "" + delimiter, true);
    }
    for (ModelField modelField: modelRecord.fields) {
        String strVal = null;

        if (modelField.expression) {
        if (UtilValidate.isNotEmpty(modelField.refField)) {
            strVal = record.getString(modelField.refField);
        }
        if (strVal == null) {
            strVal = (String)modelField.defaultValue;
        }
        } else {
        //some input lines may be less than the header model.
        if (st.hasMoreTokens()) {
            try {
            strVal = st.nextToken();
            if (strVal.equals("" + delimiter)) {
                strVal = null;
            } else if (st.hasMoreTokens()) {
                st.nextToken();
            }
            } catch (NoSuchElementException nsee) {
            throw new DataFileException("Field " + modelField.name + " could not be read from a line (" + lineNum + ") with only " +
                line.length() + " chars.", nsee);
            }                
        }
        else { //if input line is less than the header model then pad with null
            strVal = null;
        }
        }
        try {
        if (textDelimiter != null && strVal != null && (strVal.startsWith(textDelimiter) && (!strVal.endsWith(textDelimiter) || strVal.length()==1))) {
            strVal = strVal.concat(""+delimiter);
            while (!strVal.endsWith(textDelimiter)) {
                strVal = strVal.concat(st.nextToken());
            }
            st.nextToken();
        }
        if (textDelimiter != null && strVal != null && (strVal.startsWith(textDelimiter) && strVal.endsWith(textDelimiter))) {
            strVal = strVal.substring(textDelimiter.length(), strVal.length() - textDelimiter.length());
        }
        record.setString(modelField.name, strVal);
        } catch (java.text.ParseException e) {
        throw new DataFileException("Could not parse field " + modelField.name + ", format string \"" + modelField.format + "\" with value " + strVal +
            " on line " + lineNum, e);
        } catch (java.lang.NumberFormatException e) {
        throw new DataFileException("Number not valid for field " + modelField.name + ", format string \"" + modelField.format + "\" with value " +
            strVal + " on line " + lineNum, e);
        }
    }
    return record;
    }

}

