/*
 * Copyright 2013-2014 eBay Software Foundation
 *
 * Licensed 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 com.kylinolap.cube.kv;

import com.kylinolap.cube.CubeSegment;
import com.kylinolap.cube.cuboid.Cuboid;
import com.kylinolap.metadata.model.cube.TblColRef;
import org.apache.hadoop.hbase.util.Bytes;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * @author George Song (ysong1)
 */
public class RowKeyEncoder extends AbstractRowKeyEncoder {

    private int bytesLength;
    protected int headerLength;
    private RowKeyColumnIO colIO;

    protected RowKeyEncoder(CubeSegment cubeSeg, Cuboid cuboid) {
        super(cuboid);
        colIO = new RowKeyColumnIO(cubeSeg);
        bytesLength = headerLength = RowConstants.ROWKEY_CUBOIDID_LEN; // header
        for (TblColRef column : cuboid.getColumns()) {
            bytesLength += colIO.getColumnLength(column);
        }
    }

    public RowKeyColumnIO getColumnIO() {
        return colIO;
    }

    public int getColumnOffset(TblColRef col) {
        int offset = RowConstants.ROWKEY_CUBOIDID_LEN;

        for (TblColRef dimCol : cuboid.getColumns()) {
            if (col.equals(dimCol))
                return offset;
            offset += colIO.getColumnLength(dimCol);
        }

        throw new IllegalArgumentException("Column " + col + " not found on cuboid " + cuboid);
    }

    public int getColumnLength(TblColRef col) {
        return colIO.getColumnLength(col);
    }

    public int getRowKeyLength() {
        return bytesLength;
    }

    public int getHeaderLength() {
        return headerLength;
    }

    @Override
    public byte[] encode(Map<TblColRef, String> valueMap) {
        List<byte[]> valueList = new ArrayList<byte[]>();
        for (TblColRef bdCol : cuboid.getColumns()) {
            String value = valueMap.get(bdCol);
            valueList.add(valueStringToBytes(value));
        }
        byte[][] values = valueList.toArray(RowConstants.BYTE_ARR_MARKER);
        return encode(values);
    }

    public byte[] valueStringToBytes(String value) {
        if (value == null)
            return null;
        else
            return Bytes.toBytes(value);
    }

    @Override
    public byte[] encode(byte[][] values) {
        byte[] bytes = new byte[this.bytesLength];
        int offset = fillHeader(bytes, values);

        for (int i = 0; i < cuboid.getColumns().size(); i++) {
            TblColRef column = cuboid.getColumns().get(i);
            int colLength = colIO.getColumnLength(column);
            byte[] value = values[i];
            if (value == null) {
                fillColumnValue(column, colLength, null, 0, bytes, offset);
            } else {
                fillColumnValue(column, colLength, value, value.length, bytes, offset);
            }
            offset += colLength;

        }
        return bytes;
    }

    protected int fillHeader(byte[] bytes, byte[][] values) {
        int offset = 0;
        System.arraycopy(cuboid.getBytes(), 0, bytes, offset, RowConstants.ROWKEY_CUBOIDID_LEN);
        offset += RowConstants.ROWKEY_CUBOIDID_LEN;
        if (this.headerLength != offset) {
            throw new IllegalStateException("Expected header length is " + headerLength
                    + ". But the offset is " + offset);
        }
        return offset;
    }

    protected void fillColumnValue(TblColRef column, int columnLen, byte[] value, int valueLen,
                                   byte[] outputValue, int outputValueOffset) {
        // special null value case
        if (value == null) {
            byte[] valueBytes = defaultValue(columnLen);
            System.arraycopy(valueBytes, 0, outputValue, outputValueOffset, columnLen);
            return;
        }

        colIO.writeColumn(column, value, valueLen, this.blankByte, outputValue, outputValueOffset);
    }

    protected byte[] defaultValue(int length) {
        byte[] values = new byte[length];
        Arrays.fill(values, this.blankByte);
        return values;
    }

}
