/**
 * 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.hcatalog.mapreduce;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;

import junit.framework.TestCase;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hive.cli.CliSessionState;
import org.apache.hadoop.hive.conf.HiveConf;
import org.apache.hadoop.hive.metastore.MetaStoreUtils;
import org.apache.hadoop.hive.ql.Driver;
import org.apache.hadoop.hive.ql.session.SessionState;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;
import org.apache.hcatalog.HcatTestUtils;
import org.apache.hcatalog.common.HCatConstants;
import org.apache.hcatalog.common.HCatException;
import org.apache.hcatalog.common.HCatUtil;
import org.apache.hcatalog.data.DefaultHCatRecord;
import org.apache.hcatalog.data.schema.HCatFieldSchema;
import org.apache.hcatalog.data.schema.HCatSchema;
import org.apache.pig.ExecType;
import org.apache.pig.PigServer;
import org.apache.pig.data.Tuple;
import org.junit.Test;

public class TestSequenceFileReadWrite extends TestCase {
  private static final String TEST_DATA_DIR = System.getProperty("user.dir") +
      "/build/test/data/" + TestSequenceFileReadWrite.class.getCanonicalName();
  private static final String TEST_WAREHOUSE_DIR = TEST_DATA_DIR + "/warehouse";
  private static final String INPUT_FILE_NAME = TEST_DATA_DIR + "/input.data";

    private static Driver driver;
    private static PigServer server;
    private static String[] input;
    private static HiveConf hiveConf;

    public void Initialize() throws Exception {
        hiveConf = new HiveConf(this.getClass());
        hiveConf.set(HiveConf.ConfVars.PREEXECHOOKS.varname, "");
        hiveConf.set(HiveConf.ConfVars.POSTEXECHOOKS.varname, "");
        hiveConf.set(HiveConf.ConfVars.HIVE_SUPPORT_CONCURRENCY.varname, "false");
        hiveConf.set(HiveConf.ConfVars.METASTOREWAREHOUSE.varname, TEST_WAREHOUSE_DIR);
        driver = new Driver(hiveConf);
        SessionState.start(new CliSessionState(hiveConf));

        new File(TEST_WAREHOUSE_DIR).mkdirs();

        int numRows = 3;
        input = new String[numRows];
        for (int i = 0; i < numRows; i++) {
            String col1 = "a" + i;
            String col2 = "b" + i;
            input[i] = i + "," + col1 + "," + col2;
        }
        HcatTestUtils.createTestDataFile(INPUT_FILE_NAME, input);
        server = new PigServer(ExecType.LOCAL);
    }

    @Test
   public void testSequenceTableWriteRead() throws Exception{
        Initialize();
        String createTable = "CREATE TABLE demo_table(a0 int, a1 String, a2 String) STORED AS SEQUENCEFILE";
        driver.run("drop table demo_table");
        int retCode1 = driver.run(createTable).getResponseCode();
        assertTrue(retCode1 == 0);

        server.setBatchOn();
        server.registerQuery("A = load '"
                + INPUT_FILE_NAME
                + "' using PigStorage(',') as (a0:int,a1:chararray,a2:chararray);");
        server.registerQuery("store A into 'demo_table' using org.apache.hcatalog.pig.HCatStorer();");
        server.executeBatch();

        server.registerQuery("B = load 'demo_table' using org.apache.hcatalog.pig.HCatLoader();");
        Iterator<Tuple> XIter = server.openIterator("B");
        int numTuplesRead = 0;
        while (XIter.hasNext()) {
            Tuple t = XIter.next();
            assertEquals(3, t.size());
            assertEquals(t.get(0).toString(), "" + numTuplesRead);
            assertEquals(t.get(1).toString(), "a" + numTuplesRead);
            assertEquals(t.get(2).toString(), "b" + numTuplesRead);
            numTuplesRead++;
        }
        assertEquals(input.length, numTuplesRead);
   }

    @Test
    public void testTextTableWriteRead() throws Exception{
        Initialize();
        String createTable = "CREATE TABLE demo_table_1(a0 int, a1 String, a2 String) STORED AS TEXTFILE";
        driver.run("drop table demo_table_1");
        int retCode1 = driver.run(createTable).getResponseCode();
        assertTrue(retCode1 == 0);

        server.setBatchOn();
        server.registerQuery("A = load '"
                + INPUT_FILE_NAME
                + "' using PigStorage(',') as (a0:int,a1:chararray,a2:chararray);");
        server.registerQuery("store A into 'demo_table_1' using org.apache.hcatalog.pig.HCatStorer();");
        server.executeBatch();

        server.registerQuery("B = load 'demo_table_1' using org.apache.hcatalog.pig.HCatLoader();");
        Iterator<Tuple> XIter = server.openIterator("B");
        int numTuplesRead = 0;
        while (XIter.hasNext()) {
            Tuple t = XIter.next();
            assertEquals(3, t.size());
            assertEquals(t.get(0).toString(), "" + numTuplesRead);
            assertEquals(t.get(1).toString(), "a" + numTuplesRead);
            assertEquals(t.get(2).toString(), "b" + numTuplesRead);
            numTuplesRead++;
        }
        assertEquals(input.length, numTuplesRead);
    }

    @Test
    public void testSequenceTableWriteReadMR() throws Exception{
        Initialize();
        String createTable = "CREATE TABLE demo_table_2(a0 int, a1 String, a2 String) STORED AS SEQUENCEFILE";
        driver.run("drop table demo_table_2");
        int retCode1 = driver.run(createTable).getResponseCode();
        assertTrue(retCode1 == 0);

        Configuration conf = new Configuration();
        conf.set(HCatConstants.HCAT_KEY_HIVE_CONF,
                HCatUtil.serialize(hiveConf.getAllProperties()));
        Job job = new Job(conf, "Write-hcat-seq-table");
        job.setJarByClass(TestSequenceFileReadWrite.class);

        job.setMapperClass(Map.class);
        job.setOutputKeyClass(NullWritable.class);
        job.setOutputValueClass(DefaultHCatRecord.class);
        job.setInputFormatClass(TextInputFormat.class);
        TextInputFormat.setInputPaths(job, INPUT_FILE_NAME);

        HCatOutputFormat.setOutput(job, OutputJobInfo.create(
                MetaStoreUtils.DEFAULT_DATABASE_NAME, "demo_table_2", null));
        job.setOutputFormatClass(HCatOutputFormat.class);
        HCatOutputFormat.setSchema(job, getSchema());
        job.setNumReduceTasks(0);
        assertTrue(job.waitForCompletion(true));
        if (!HcatTestUtils.isHadoop23()) {
            new FileOutputCommitterContainer(job, null).commitJob(job);
        }
        assertTrue(job.isSuccessful());

        server.setBatchOn();
        server.registerQuery("C = load 'default.demo_table_2' using org.apache.hcatalog.pig.HCatLoader();");
        server.executeBatch();
        Iterator<Tuple> XIter = server.openIterator("C");
        int numTuplesRead = 0;
        while (XIter.hasNext()) {
            Tuple t = XIter.next();
            assertEquals(3, t.size());
            assertEquals(t.get(0).toString(), "" + numTuplesRead);
            assertEquals(t.get(1).toString(), "a" + numTuplesRead);
            assertEquals(t.get(2).toString(), "b" + numTuplesRead);
            numTuplesRead++;
        }
        assertEquals(input.length, numTuplesRead);
    }

    @Test
    public void testTextTableWriteReadMR() throws Exception {
        Initialize();
        String createTable = "CREATE TABLE demo_table_3(a0 int, a1 String, a2 String) STORED AS TEXTFILE";
        driver.run("drop table demo_table_3");
        int retCode1 = driver.run(createTable).getResponseCode();
        assertTrue(retCode1 == 0);

        Configuration conf = new Configuration();
        conf.set(HCatConstants.HCAT_KEY_HIVE_CONF,
                HCatUtil.serialize(hiveConf.getAllProperties()));
        Job job = new Job(conf, "Write-hcat-text-table");
        job.setJarByClass(TestSequenceFileReadWrite.class);

        job.setMapperClass(Map.class);
        job.setOutputKeyClass(NullWritable.class);
        job.setOutputValueClass(DefaultHCatRecord.class);
        job.setInputFormatClass(TextInputFormat.class);
        job.setNumReduceTasks(0);
        TextInputFormat.setInputPaths(job, INPUT_FILE_NAME);

        HCatOutputFormat.setOutput(job, OutputJobInfo.create(
                MetaStoreUtils.DEFAULT_DATABASE_NAME, "demo_table_3", null));
        job.setOutputFormatClass(HCatOutputFormat.class);
        HCatOutputFormat.setSchema(job, getSchema());
        assertTrue(job.waitForCompletion(true));
        if (!HcatTestUtils.isHadoop23()) {
            new FileOutputCommitterContainer(job, null).commitJob(job);
        }
        assertTrue(job.isSuccessful());

        server.setBatchOn();
        server.registerQuery("D = load 'default.demo_table_3' using org.apache.hcatalog.pig.HCatLoader();");
        server.executeBatch();
        Iterator<Tuple> XIter = server.openIterator("D");
        int numTuplesRead = 0;
        while (XIter.hasNext()) {
            Tuple t = XIter.next();
            assertEquals(3, t.size());
            assertEquals(t.get(0).toString(), "" + numTuplesRead);
            assertEquals(t.get(1).toString(), "a" + numTuplesRead);
            assertEquals(t.get(2).toString(), "b" + numTuplesRead);
            numTuplesRead++;
        }
        assertEquals(input.length, numTuplesRead);
    }


  public static class Map extends Mapper<LongWritable, Text, NullWritable, DefaultHCatRecord>{

      public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
          String[] cols = value.toString().split(",");
          DefaultHCatRecord record = new DefaultHCatRecord(3);
          record.set(0,Integer.parseInt(cols[0]));
          record.set(1,cols[1]);
          record.set(2,cols[2]);
          context.write(NullWritable.get(), record);
      }
    }

  private HCatSchema getSchema() throws HCatException {
      HCatSchema schema = new HCatSchema(new ArrayList<HCatFieldSchema>());
      schema.append(new HCatFieldSchema("a0", HCatFieldSchema.Type.INT,
              ""));
      schema.append(new HCatFieldSchema("a1",
              HCatFieldSchema.Type.STRING, ""));
      schema.append(new HCatFieldSchema("a2",
              HCatFieldSchema.Type.STRING, ""));
      return schema;
  }

}
