package mobvista.dmp.format;


import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hive.ql.io.RCFile;
import org.apache.hadoop.hive.ql.io.RCFile.Reader;
import org.apache.hadoop.hive.serde2.columnar.BytesRefArrayWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.mapreduce.InputSplit;
import org.apache.hadoop.mapreduce.RecordReader;
import org.apache.hadoop.mapreduce.TaskAttemptContext;
import org.apache.hadoop.mapreduce.lib.input.FileSplit;

import java.io.IOException;

/**
 * RCFileRecordReader.
 *
 * @param <K>
 * @param <V>
 */
public class RCFileRecordReader<K extends LongWritable, V extends BytesRefArrayWritable>
        extends RecordReader<LongWritable, BytesRefArrayWritable>
{

    private Reader in;
    private long start;
    private long end;
    private boolean more = true;
    protected Configuration conf;
    private LongWritable key = null;
    private BytesRefArrayWritable value = null;

    public RCFileRecordReader(Configuration conf, FileSplit split)
            throws IOException
    {
        key = new LongWritable();
        value = new BytesRefArrayWritable();
        Path path = split.getPath();
        FileSystem fs = path.getFileSystem(conf);
        this.in = new RCFile.Reader(fs, path, conf);
        this.end = split.getStart() + split.getLength();
        this.conf = conf;

        if (split.getStart() > in.getPosition())
        {
            in.sync(split.getStart()); // sync to start
        }

        this.start = in.getPosition();
        more = start < end;
    }

    @Override
    public void initialize(InputSplit split, TaskAttemptContext context)
            throws IOException, InterruptedException
    {
        // TODO Auto-generated method stub
    /*
	FileSplit fsplit = (FileSplit)split;
    Path path = fsplit.getPath();
    FileSystem fs = path.getFileSystem(conf);
    this.in = new RCFile.Reader(fs, path, conf);
    this.end = fsplit.getStart() + fsplit.getLength();
    this.conf = conf;

    if (fsplit.getStart() > in.getPosition()) {
      in.sync(fsplit.getStart()); // sync to start
    }

    this.start = in.getPosition();
    more = start < end;
  	*/
    }

    @Override
    public boolean nextKeyValue() throws IOException, InterruptedException
    {
        // TODO Auto-generated method stub
        more = next(key);
        if (more)
        {
            in.getCurrentRow(value);
        }
        return more;
    }

    protected boolean next(LongWritable key) throws IOException
    {
        if (!more)
        {
            return false;
        }
        more = in.next(key);
        if (!more)
        {
            return false;
        }
        long lastSeenSyncPos = in.lastSeenSyncPos();
        if (lastSeenSyncPos >= end)
        {
            more = false;
            return more;
        }
        return more;
    }

    @Override
    public LongWritable getCurrentKey() throws IOException, InterruptedException
    {
        // TODO Auto-generated method stub
        return key;
    }

    @Override
    public BytesRefArrayWritable getCurrentValue() throws IOException,
            InterruptedException
    {
        // TODO Auto-generated method stub
        return value;
    }

    /**
     * Return the progress within the input split.
     *
     * @return 0.0 to 1.0 of the input byte range
     */
    public float getProgress() throws IOException
    {
        if (end == start)
        {
            return 0.0f;
        } else
        {
            return Math.min(1.0f, (in.getPosition() - start) / (float) (end - start));
        }
    }

    public void close() throws IOException
    {
        in.close();
    }
  /*
  public long getPos() throws IOException {
    return in.getPosition();
  }

  protected void seek(long pos) throws IOException {
    in.seek(pos);
  }

  public long getStart() {
    return start;
  }
  */
}
