/*
 * 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.phoenix.schema;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.hadoop.io.Writable;
import org.apache.hadoop.io.WritableUtils;
import org.apache.phoenix.schema.types.PDataType;
import org.apache.phoenix.util.SizedUtil;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;

/**
 * 
 * Simple flat schema over a byte array where fields may be any of {@link org.apache.phoenix.schema.types.PDataType}.
 * Optimized for positional access by index.
 *
 * 
 * @since 0.1
 */
public abstract class ValueSchema implements Writable {
    public static final int ESTIMATED_VARIABLE_LENGTH_SIZE = 10;
    private int[] fieldIndexByPosition;
    private List<Field> fields;
    private int estimatedLength;
    private boolean isFixedLength;
    private boolean isMaxLength;
    private int minNullable;
    // Only applicable for RowKeySchema (and only due to PHOENIX-2067), but
    // added here as this is where serialization is done (and we need to
    // maintain the same serialization shape for b/w compat).
    protected boolean rowKeyOrderOptimizable;
    
    public ValueSchema() {
    }
    
    protected ValueSchema(int minNullable, List<Field> fields) {
        this(minNullable, fields, true);
    }
    
    protected ValueSchema(int minNullable, List<Field> fields, boolean rowKeyOrderOptimizable) {
        init(minNullable, fields, rowKeyOrderOptimizable);
    }
    
    @Override
    public String toString() {
        return fields.toString();
    }
    
    public int getEstimatedSize() { // Memory size of ValueSchema
        int count = fieldIndexByPosition.length;
        return SizedUtil.OBJECT_SIZE + SizedUtil.POINTER_SIZE + SizedUtil.INT_SIZE * (4 + count) + 
                SizedUtil.ARRAY_SIZE + count * Field.ESTIMATED_SIZE + SizedUtil.sizeOfArrayList(count);
    }

    private void init(int minNullable, List<Field> fields, boolean rowKeyOrderOptimizable) {
        this.rowKeyOrderOptimizable = rowKeyOrderOptimizable;
        this.minNullable = minNullable;
        this.fields = ImmutableList.copyOf(fields);
        int estimatedLength = 0;
        boolean isMaxLength = true, isFixedLength = true;
        int positions = 0;
        for (Field field : fields) {
            int fieldEstLength = 0;
            PDataType type = field.getDataType();
            if (type != null) {
                Integer byteSize = type.getByteSize();
                if (type.isFixedWidth()) {
                    fieldEstLength += field.getByteSize();
                } else {
                    isFixedLength = false;
                    // Account for vint for length if not fixed
                    if (byteSize == null) {
                        isMaxLength = false;
                        fieldEstLength += ESTIMATED_VARIABLE_LENGTH_SIZE;
                    } else {
                        fieldEstLength += WritableUtils.getVIntSize(byteSize);
                        fieldEstLength = byteSize;
                    }
                }
            }
            positions += field.getCount();
            estimatedLength += fieldEstLength * field.getCount();
        }
        fieldIndexByPosition = new int[positions];
        for (int i = 0, j= 0; i < fields.size(); i++) {
            Field field = fields.get(i);
            Arrays.fill(fieldIndexByPosition, j, j + field.getCount(), i);
            j += field.getCount();
        }
        this.isFixedLength = isFixedLength;
        this.isMaxLength = isMaxLength;
        this.estimatedLength = estimatedLength;
    }
    
    public int getFieldCount() {
        return fieldIndexByPosition.length;
    }
    
    public List<Field> getFields() {
        return fields;
    }
    
    /**
     * @return true if all types are fixed width
     */
    public boolean isFixedLength() {
        return isFixedLength;
    }
    
    /**
     * @return true if {@link #getEstimatedValueLength()} returns the maximum length
     * of a serialized value for this schema
     */
    public boolean isMaxLength() {
        return isMaxLength;
    }
    
    /**
     * @return estimated size in bytes of a serialized value for this schema
     */
    public int getEstimatedValueLength() {
        return estimatedLength;
    }
    
    /**
     * Non-nullable fields packed to the left so that we do not need to store trailing nulls.
     * Knowing the minimum position of a nullable field enables this.
     * @return the minimum position of a nullable field
     */
    public int getMinNullable() {
        return minNullable;
    }
    
    public static final class Field implements Writable, PDatum {
        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + byteSize;
            result = prime * result + (type == null ? 0 : type.hashCode());            
            result = prime * result + sortOrder.hashCode();
            result = prime * result + (isNullable ? 1231 : 1237);
            return result;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) return true;
            if (obj == null) return false;
            if (getClass() != obj.getClass()) return false;
            Field other = (Field)obj;
            if (byteSize != other.byteSize) return false;
            if (sortOrder != other.sortOrder) return false;
            if (isNullable != other.isNullable) return false;
            if (type != other.type) return false;
            return true;
        }
        
        public static final int ESTIMATED_SIZE = SizedUtil.OBJECT_SIZE + SizedUtil.POINTER_SIZE * 2 + SizedUtil.INT_SIZE * 3;

        private int count;
        private PDataType type;
        private int byteSize = 0;
        private boolean isNullable;
        private SortOrder sortOrder;
        
        public Field() {
        }
        
        private Field(PDatum datum, boolean isNullable, int count, SortOrder sortOrder) {
            Preconditions.checkNotNull(sortOrder);
            this.type = datum.getDataType();
            this.sortOrder = sortOrder;
            this.count = count;
            this.isNullable = isNullable;
            if (this.type != null && this.type.isFixedWidth() && this.type.getByteSize() == null) {
                if (datum.getMaxLength() != null) {
                    this.byteSize = datum.getMaxLength();
                }
            }
        }
        
        @Override
        public String toString() {
            return (count == 1 ? "" : count + " * ") 
                    + type
                    + (byteSize == 0 ? "" : "(" + byteSize + ")") 
                    + (isNullable ? "" : " NOT NULL") 
                    + (sortOrder == SortOrder.ASC ? "" : " " + sortOrder);
        }
        
        private Field(Field field, int count) {
            this.type = field.getDataType();
            this.byteSize = field.byteSize;
            this.count = count;
            this.sortOrder = SortOrder.getDefault();
        }
        
        @Override
        public final SortOrder getSortOrder() {
            return sortOrder;
        }
        
        @Override
        public final PDataType getDataType() {
            return type;
        }
        
        @Override
        public final boolean isNullable() {
            return isNullable;
        }
        
        public final int getByteSize() {
            return type.getByteSize() == null ? byteSize : type.getByteSize();
        }
        
        public final int getCount() {
            return count;
        }

        @Override
        public Integer getMaxLength() {
            return type.isFixedWidth() ? byteSize : null;
        }

        @Override
        public Integer getScale() {
            return null;
        }

        @Override
        public void readFields(DataInput input) throws IOException {
            // Encode isNullable in sign bit of type ordinal (offset by 1, since ordinal could be 0)
            int typeOrdinal = WritableUtils.readVInt(input);
            if (typeOrdinal < 0) {
                typeOrdinal *= -1;
                this.isNullable = true;
            }
            this.type = PDataType.values()[typeOrdinal-1];
            this.count = WritableUtils.readVInt(input);
            if (this.count < 0) {
                this.count *= -1;
                this.sortOrder = SortOrder.DESC;
            } else {
            	this.sortOrder = SortOrder.ASC;
            }
            if (this.type.isFixedWidth() && this.type.getByteSize() == null) {
                this.byteSize = WritableUtils.readVInt(input);
            }
        }

        @Override
        public void write(DataOutput output) throws IOException {
            WritableUtils.writeVInt(output, (type.ordinal() + 1) * (this.isNullable ? -1 : 1));
            WritableUtils.writeVInt(output, count * (sortOrder == SortOrder.ASC ? 1 : -1));
            if (type.isFixedWidth() && type.getByteSize() == null) {
                WritableUtils.writeVInt(output, byteSize);
            }
        }
    }
    
    public abstract static class ValueSchemaBuilder {
        protected List<Field> fields = new ArrayList<Field>();
        protected int nFields = Integer.MAX_VALUE;
        protected final int minNullable;
        
        public ValueSchemaBuilder(int minNullable) {
            this.minNullable = minNullable;
        }
        
        protected List<Field> buildFields() {
            List<Field> condensedFields = new ArrayList<Field>(fields.size());
            for (int i = 0; i < Math.min(nFields,fields.size()); ) {
                Field field = fields.get(i);
                int count = 1;
                while ( ++i < fields.size() && field.equals(fields.get(i))) {
                    count++;
                }
                condensedFields.add(count == 1 ? field : new Field(field,count));
            }
            return condensedFields;
        }

        abstract public ValueSchema build();

        public ValueSchemaBuilder setMaxFields(int nFields) {
            this.nFields = nFields;
            return this;
        }
        
        protected ValueSchemaBuilder addField(PDatum datum, boolean isNullable, SortOrder sortOrder) {
            if(fields.size() >= nFields) {
                throw new IllegalArgumentException("Adding too many fields to Schema (max " + nFields + ")");
            }
            fields.add(new Field(datum, isNullable, 1, sortOrder));
            return this;
        }
    }
    
    public int getEstimatedByteSize() {
        int size = 0;
        size += WritableUtils.getVIntSize(minNullable);
        size += WritableUtils.getVIntSize(fields.size());
        size += fields.size() * 3;
        return size;
    }
    
    public Field getField(int position) {
        return fields.get(fieldIndexByPosition[position]);
    }
    
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + minNullable;
        for (Field field : fields) {
        	result = prime * result + field.hashCode();
        }
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null) return false;
        if (getClass() != obj.getClass()) return false;
        ValueSchema other = (ValueSchema)obj;
        if (minNullable != other.minNullable) return false;
        if (fields.size() != other.fields.size()) return false;
        for (int i = 0; i < fields.size(); i++) {
        	if (!fields.get(i).equals(other.fields.get(i)))
        		return false;
        }
        return true;
    }
    
    @Override
    public void readFields(DataInput in) throws IOException {
        int minNullable = WritableUtils.readVInt(in);
        int nFields = WritableUtils.readVInt(in);
        boolean rowKeyOrderOptimizable = false;
        if (nFields < 0) {
            rowKeyOrderOptimizable = true;
            nFields *= -1;
        }
        List<Field> fields = Lists.newArrayListWithExpectedSize(nFields);
        for (int i = 0; i < nFields; i++) {
            Field field = new Field();
            field.readFields(in);
            fields.add(field);
        }
        init(minNullable, fields, rowKeyOrderOptimizable);
    }
         
    @Override
    public void write(DataOutput out) throws IOException {
        WritableUtils.writeVInt(out, minNullable);
        WritableUtils.writeVInt(out, fields.size() * (rowKeyOrderOptimizable ? -1 : 1));
        for (int i = 0; i < fields.size(); i++) {
            fields.get(i).write(out);
        }
    }

}
