/*
 * 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.drill.exec.store.hbase.config;

import static org.apache.drill.exec.store.hbase.config.HBasePersistentStoreProvider.FAMILY;
import static org.apache.drill.exec.store.hbase.config.HBasePersistentStoreProvider.QUALIFIER;

import java.io.IOException;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.NoSuchElementException;

import org.apache.drill.common.exceptions.UserException;
import org.apache.drill.exec.store.sys.BasePersistentStore;
import org.apache.drill.exec.store.sys.PersistentStoreConfig;
import org.apache.drill.exec.store.sys.PersistentStoreMode;
import org.apache.hadoop.hbase.client.Delete;
import org.apache.hadoop.hbase.client.Get;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.ResultScanner;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.client.Table;
import org.apache.hadoop.hbase.util.Bytes;

import com.google.common.collect.Iterators;

public class HBasePersistentStore<V> extends BasePersistentStore<V> {
  private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(HBasePersistentStore.class);

  private final PersistentStoreConfig<V> config;
  private final Table hbaseTable;
  private final String hbaseTableName;

  private final String tableName;
  private final byte[] tableNameStartKey;
  private final byte[] tableNameStopKey;

  public HBasePersistentStore(PersistentStoreConfig<V> config, Table table) {
    this.tableName = config.getName() + '\0';
    this.tableNameStartKey = Bytes.toBytes(tableName); // "tableName\x00"
    this.tableNameStopKey = this.tableNameStartKey.clone();
    this.tableNameStopKey[tableNameStartKey.length-1] = 1;
    this.config = config;
    this.hbaseTable = table;
    this.hbaseTableName = table.getName().getNameAsString();
  }

  @Override
  public PersistentStoreMode getMode() {
    return PersistentStoreMode.PERSISTENT;
  }

  @Override
  public boolean contains(String key) {
    try {
      Get get = new Get(row(key));
      get.addColumn(FAMILY, QUALIFIER);
      return hbaseTable.exists(get);
    } catch (IOException e) {
      throw UserException
          .dataReadError(e)
          .message("Caught error while checking row existence '%s' for table '%s'", key, hbaseTableName)
          .build(logger);
    }
  }

  @Override
  public V get(String key) {
    return get(key, FAMILY);
  }

  protected synchronized V get(String key, byte[] family) {
    try {
      Get get = new Get(row(key));
      get.addColumn(family, QUALIFIER);
      Result r = hbaseTable.get(get);
      if(r.isEmpty()){
        return null;
      }
      return value(r);
    } catch (IOException e) {
      throw UserException.dataReadError(e)
          .message("Caught error while getting row '%s' from for table '%s'", key, hbaseTableName)
          .build(logger);
    }
  }

  @Override
  public void put(String key, V value) {
    put(key, FAMILY, value);
  }

  protected synchronized void put(String key, byte[] family, V value) {
    try {
      Put put = new Put(row(key));
      put.addColumn(family, QUALIFIER, bytes(value));
      hbaseTable.put(put);
    } catch (IOException e) {
      throw UserException.dataReadError(e)
          .message("Caught error while putting row '%s' into table '%s'", key, hbaseTableName)
          .build(logger);
    }
  }

  @Override
  public synchronized boolean putIfAbsent(String key, V value) {
    try {
      Put put = new Put(row(key));
      put.addColumn(FAMILY, QUALIFIER, bytes(value));
      return hbaseTable.checkAndPut(put.getRow(), FAMILY, QUALIFIER, null /*absent*/, put);
    } catch (IOException e) {
      throw UserException.dataReadError(e)
          .message("Caught error while putting row '%s' into table '%s'", key, hbaseTableName)
          .build(logger);
    }
  }

  @Override
  public synchronized void delete(String key) {
    delete(row(key));
  }

  @Override
  public Iterator<Entry<String, V>> getRange(int skip, int take) {
    final Iterator<Entry<String, V>> iter = new Iter(take);
    Iterators.advance(iter, skip);
    return Iterators.limit(iter, take);
  }

  private byte[] row(String key) {
    return Bytes.toBytes(this.tableName + key);
  }

  private byte[] bytes(V value) {
    try {
      return config.getSerializer().serialize(value);
    } catch (IOException e) {
      throw UserException.dataReadError(e).build(logger);
    }
  }

  private V value(Result result) {
    try {
      return config.getSerializer().deserialize(result.value());
    } catch (IOException e) {
      throw UserException.dataReadError(e).build(logger);
    }
  }

  private void delete(byte[] row) {
    try {
      Delete del = new Delete(row);
      hbaseTable.delete(del);
    } catch (IOException e) {
      throw UserException.dataReadError(e)
          .message("Caught error while deleting row '%s' from for table '%s'", Bytes.toStringBinary(row), hbaseTableName)
          .build(logger);
    }
  }

  private class Iter implements Iterator<Entry<String, V>> {
    private ResultScanner scanner;
    private Result current = null;
    private Result last = null;
    private boolean done = false;

    Iter(int take) {
      try {
        Scan scan = new Scan(tableNameStartKey, tableNameStopKey);
        scan.addColumn(FAMILY, QUALIFIER);
        scan.setCaching(Math.min(take, 100));
        scan.setBatch(take);  // set batch size
        scanner = hbaseTable.getScanner(scan);
      } catch (IOException e) {
        throw UserException.dataReadError(e)
            .message("Caught error while creating HBase scanner for table '%s'" + hbaseTableName)
            .build(logger);
      }
    }

    @Override
    public boolean hasNext()  {
      if (!done && current == null) {
        try {
          if ((current = scanner.next()) == null) {
            done = true;
          }
        } catch (IOException e) {
          throw UserException.dataReadError(e)
              .message("Caught error while fetching rows from for table '%s'", hbaseTableName)
              .build(logger);
        }
      }

      if (done && scanner != null) {
        scanner.close();
      }
      return (current != null);
    }

    @Override
    public Entry<String, V> next() {
      if (!hasNext()) {
        throw new NoSuchElementException();
      }
      last = current;
      current = null;
      return new DeferredEntry(last);
    }

    @Override
    public void remove() {
      if (last == null) {
        throw new IllegalStateException("remove() called on HBase persistent store iterator, but there is no last row.");
      }
      delete(last.getRow());
    }

  }

  private class DeferredEntry implements Entry<String, V>{

    private Result result;

    public DeferredEntry(Result result) {
      super();
      this.result = result;
    }

    @Override
    public String getKey() {
      return Bytes.toString(result.getRow(), tableNameStartKey.length, result.getRow().length-tableNameStartKey.length);
    }

    @Override
    public V getValue() {
      return value(result);
    }

    @Override
    public V setValue(V value) {
      throw new UnsupportedOperationException();
    }

  }

  @Override
  public void close() {
  }

}
