/**
 * 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 java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Random;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.FileUtil;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.hadoop.hive.conf.HiveConf;
import org.apache.hadoop.hive.metastore.HiveMetaStore;
import org.apache.hadoop.hive.metastore.HiveMetaStoreClient;
import org.apache.hadoop.hive.metastore.api.FieldSchema;
import org.apache.hadoop.hive.metastore.api.NoSuchObjectException;
import org.apache.hadoop.hive.metastore.api.SerDeInfo;
import org.apache.hadoop.hive.metastore.api.StorageDescriptor;
import org.apache.hadoop.hive.metastore.api.Table;
import org.apache.hadoop.hive.ql.exec.FetchTask;
import org.apache.hadoop.hive.ql.exec.Utilities;
import org.apache.hadoop.hive.ql.metadata.Hive;
import org.apache.hadoop.hive.ql.metadata.Partition;
import org.apache.hadoop.hive.ql.plan.FetchWork;
import org.apache.hadoop.hive.ql.plan.PartitionDesc;
import org.apache.hadoop.hive.serde.Constants;
import org.apache.hadoop.io.BytesWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapred.JobConf;
import org.apache.hadoop.mapred.MiniMRCluster;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;
import org.apache.hcatalog.cli.SemanticAnalysis.HCatSemanticAnalyzer;
import org.apache.hcatalog.common.HCatException;
import org.apache.hcatalog.data.DefaultHCatRecord;
import org.apache.hcatalog.data.HCatRecord;
import org.apache.hcatalog.data.schema.HCatFieldSchema;
import org.apache.hcatalog.data.schema.HCatSchema;
import org.apache.hcatalog.data.schema.HCatSchemaUtils;
import org.apache.hcatalog.mapreduce.MultiOutputFormat.JobConfigurer;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class TestHCatMultiOutputFormat {

    private static final Logger LOG = LoggerFactory.getLogger(TestHCatMultiOutputFormat.class);

    private static final String DATABASE = "default";
    private static final String[] tableNames = {"test1", "test2", "test3"};
    private static final String[] tablePerms = {"755", "750", "700"};
    private static Path warehousedir = null;
    private static HashMap<String, HCatSchema> schemaMap = new HashMap<String, HCatSchema>();
    private static HiveMetaStoreClient hmsc;
    private static MiniMRCluster mrCluster;
    private static Configuration mrConf;
    private static HiveConf hiveConf;
    private static File workDir;

    private static final String msPort = "20199";
    private static Thread t;

    static {
        schemaMap.put(tableNames[0], new HCatSchema(ColumnHolder.hCattest1Cols));
        schemaMap.put(tableNames[1], new HCatSchema(ColumnHolder.hCattest2Cols));
        schemaMap.put(tableNames[2], new HCatSchema(ColumnHolder.hCattest3Cols));
    }

    private static class RunMS implements Runnable {

        @Override
        public void run() {
            try {
                String warehouseConf = HiveConf.ConfVars.METASTOREWAREHOUSE.varname + "="
                    + warehousedir.toString();
                HiveMetaStore.main(new String[]{"-v", "-p", msPort, "--hiveconf", warehouseConf});
            } catch (Throwable t) {
                System.err.println("Exiting. Got exception from metastore: " + t.getMessage());
            }
        }

    }

    /**
     * Private class which holds all the data for the test cases
     */
    private static class ColumnHolder {

        private static ArrayList<HCatFieldSchema> hCattest1Cols = new ArrayList<HCatFieldSchema>();
        private static ArrayList<HCatFieldSchema> hCattest2Cols = new ArrayList<HCatFieldSchema>();
        private static ArrayList<HCatFieldSchema> hCattest3Cols = new ArrayList<HCatFieldSchema>();

        private static ArrayList<FieldSchema> partitionCols = new ArrayList<FieldSchema>();
        private static ArrayList<FieldSchema> test1Cols = new ArrayList<FieldSchema>();
        private static ArrayList<FieldSchema> test2Cols = new ArrayList<FieldSchema>();
        private static ArrayList<FieldSchema> test3Cols = new ArrayList<FieldSchema>();

        private static HashMap<String, List<FieldSchema>> colMapping = new HashMap<String, List<FieldSchema>>();

        static {
            try {
                FieldSchema keyCol = new FieldSchema("key", Constants.STRING_TYPE_NAME, "");
                test1Cols.add(keyCol);
                test2Cols.add(keyCol);
                test3Cols.add(keyCol);
                hCattest1Cols.add(HCatSchemaUtils.getHCatFieldSchema(keyCol));
                hCattest2Cols.add(HCatSchemaUtils.getHCatFieldSchema(keyCol));
                hCattest3Cols.add(HCatSchemaUtils.getHCatFieldSchema(keyCol));
                FieldSchema valueCol = new FieldSchema("value", Constants.STRING_TYPE_NAME, "");
                test1Cols.add(valueCol);
                test3Cols.add(valueCol);
                hCattest1Cols.add(HCatSchemaUtils.getHCatFieldSchema(valueCol));
                hCattest3Cols.add(HCatSchemaUtils.getHCatFieldSchema(valueCol));
                FieldSchema extraCol = new FieldSchema("extra", Constants.STRING_TYPE_NAME, "");
                test3Cols.add(extraCol);
                hCattest3Cols.add(HCatSchemaUtils.getHCatFieldSchema(extraCol));
                colMapping.put("test1", test1Cols);
                colMapping.put("test2", test2Cols);
                colMapping.put("test3", test3Cols);
            } catch (HCatException e) {
                LOG.error("Error in setting up schema fields for the table", e);
                throw new RuntimeException(e);
            }
        }

        static {
            partitionCols.add(new FieldSchema("ds", Constants.STRING_TYPE_NAME, ""));
            partitionCols.add(new FieldSchema("cluster", Constants.STRING_TYPE_NAME, ""));
        }
    }

    @BeforeClass
    public static void setup() throws Exception {
        String testDir = System.getProperty("test.data.dir", "./");
        testDir = testDir + "/test_multitable_" + Math.abs(new Random().nextLong()) + "/";
        workDir = new File(new File(testDir).getCanonicalPath());
        FileUtil.fullyDelete(workDir);
        workDir.mkdirs();

        warehousedir = new Path(workDir + "/warehouse");

        // Run hive metastore server
        t = new Thread(new RunMS());
        t.start();

        // LocalJobRunner does not work with mapreduce OutputCommitter. So need
        // to use MiniMRCluster. MAPREDUCE-2350
        Configuration conf = new Configuration(true);
        FileSystem fs = FileSystem.get(conf);
        System.setProperty("hadoop.log.dir", new File(workDir, "/logs").getAbsolutePath());
        mrCluster = new MiniMRCluster(1, fs.getUri().toString(), 1, null, null,
            new JobConf(conf));
        mrConf = mrCluster.createJobConf();
        fs.mkdirs(warehousedir);

        initializeSetup();
    }

    private static void initializeSetup() throws Exception {

        hiveConf = new HiveConf(mrConf, TestHCatMultiOutputFormat.class);
        hiveConf.set("hive.metastore.local", "false");
        hiveConf.setVar(HiveConf.ConfVars.METASTOREURIS, "thrift://localhost:" + msPort);
        hiveConf.setIntVar(HiveConf.ConfVars.METASTORETHRIFTRETRIES, 3);

        hiveConf.set(HiveConf.ConfVars.SEMANTIC_ANALYZER_HOOK.varname,
            HCatSemanticAnalyzer.class.getName());
        hiveConf.set(HiveConf.ConfVars.PREEXECHOOKS.varname, "");
        hiveConf.set(HiveConf.ConfVars.POSTEXECHOOKS.varname, "");
        hiveConf.set(HiveConf.ConfVars.HIVE_SUPPORT_CONCURRENCY.varname, "false");
        System.setProperty(HiveConf.ConfVars.PREEXECHOOKS.varname, " ");
        System.setProperty(HiveConf.ConfVars.POSTEXECHOOKS.varname, " ");

        hiveConf.set(HiveConf.ConfVars.METASTOREWAREHOUSE.varname, warehousedir.toString());
        try {
            hmsc = new HiveMetaStoreClient(hiveConf, null);
            initalizeTables();
        } catch (Throwable e) {
            LOG.error("Exception encountered while setting up testcase", e);
            throw new Exception(e);
        } finally {
            hmsc.close();
        }
    }

    private static void initalizeTables() throws Exception {
        for (String table : tableNames) {
            try {
                if (hmsc.getTable(DATABASE, table) != null) {
                    hmsc.dropTable(DATABASE, table);
                }
            } catch (NoSuchObjectException ignored) {
            }
        }
        for (int i = 0; i < tableNames.length; i++) {
            createTable(tableNames[i], tablePerms[i]);
        }
    }

    private static void createTable(String tableName, String tablePerm) throws Exception {
        Table tbl = new Table();
        tbl.setDbName(DATABASE);
        tbl.setTableName(tableName);
        StorageDescriptor sd = new StorageDescriptor();
        sd.setCols(ColumnHolder.colMapping.get(tableName));
        tbl.setSd(sd);
        sd.setParameters(new HashMap<String, String>());
        sd.setSerdeInfo(new SerDeInfo());
        sd.getSerdeInfo().setName(tbl.getTableName());
        sd.getSerdeInfo().setParameters(new HashMap<String, String>());
        sd.setInputFormat(org.apache.hadoop.hive.ql.io.RCFileInputFormat.class.getName());
        sd.setOutputFormat(org.apache.hadoop.hive.ql.io.RCFileOutputFormat.class.getName());
        sd.getSerdeInfo().getParameters().put(
            org.apache.hadoop.hive.serde.Constants.SERIALIZATION_FORMAT, "1");
        sd.getSerdeInfo().setSerializationLib(
            org.apache.hadoop.hive.serde2.columnar.ColumnarSerDe.class.getName());
        tbl.setPartitionKeys(ColumnHolder.partitionCols);

        hmsc.createTable(tbl);
        FileSystem fs = FileSystem.get(mrConf);
        fs.setPermission(new Path(warehousedir, tableName), new FsPermission(tablePerm));
    }

    @AfterClass
    public static void tearDown() throws IOException {
        FileUtil.fullyDelete(workDir);
        FileSystem fs = FileSystem.get(mrConf);
        if (fs.exists(warehousedir)) {
            fs.delete(warehousedir, true);
        }
        if (mrCluster != null) {
            mrCluster.shutdown();
        }
    }

    /**
     * Simple test case.
     * <ol>
     * <li>Submits a mapred job which writes out one fixed line to each of the tables</li>
     * <li>uses hive fetch task to read the data and see if it matches what was written</li>
     * </ol>
     *
     * @throws Exception if any error occurs
     */
    @Test
    public void testOutputFormat() throws Throwable {
        HashMap<String, String> partitionValues = new HashMap<String, String>();
        partitionValues.put("ds", "1");
        partitionValues.put("cluster", "ag");
        ArrayList<OutputJobInfo> infoList = new ArrayList<OutputJobInfo>();
        infoList.add(OutputJobInfo.create("default", tableNames[0], partitionValues));
        infoList.add(OutputJobInfo.create("default", tableNames[1], partitionValues));
        infoList.add(OutputJobInfo.create("default", tableNames[2], partitionValues));

        Job job = new Job(hiveConf, "SampleJob");

        job.setMapperClass(MyMapper.class);
        job.setInputFormatClass(TextInputFormat.class);
        job.setOutputFormatClass(MultiOutputFormat.class);
        job.setNumReduceTasks(0);

        JobConfigurer configurer = MultiOutputFormat.createConfigurer(job);

        for (int i = 0; i < tableNames.length; i++) {
            configurer.addOutputFormat(tableNames[i], HCatOutputFormat.class, BytesWritable.class,
                HCatRecord.class);
            HCatOutputFormat.setOutput(configurer.getJob(tableNames[i]), infoList.get(i));
            HCatOutputFormat.setSchema(configurer.getJob(tableNames[i]),
                schemaMap.get(tableNames[i]));
        }
        configurer.configure();

        Path filePath = createInputFile();
        FileInputFormat.addInputPath(job, filePath);
        Assert.assertTrue(job.waitForCompletion(true));

        ArrayList<String> outputs = new ArrayList<String>();
        for (String tbl : tableNames) {
            outputs.add(getTableData(tbl, "default").get(0));
        }
        Assert.assertEquals("Comparing output of table " +
            tableNames[0] + " is not correct", outputs.get(0), "a,a,1,ag");
        Assert.assertEquals("Comparing output of table " +
            tableNames[1] + " is not correct", outputs.get(1), "a,1,ag");
        Assert.assertEquals("Comparing output of table " +
            tableNames[2] + " is not correct", outputs.get(2), "a,a,extra,1,ag");

        // Check permisssion on partition dirs and files created
        for (int i = 0; i < tableNames.length; i++) {
            Path partitionFile = new Path(warehousedir + "/" + tableNames[i]
                + "/ds=1/cluster=ag/part-m-00000");
            FileSystem fs = partitionFile.getFileSystem(mrConf);
            Assert.assertEquals("File permissions of table " + tableNames[i] + " is not correct",
                fs.getFileStatus(partitionFile).getPermission(),
                new FsPermission(tablePerms[i]));
            Assert.assertEquals("File permissions of table " + tableNames[i] + " is not correct",
                fs.getFileStatus(partitionFile.getParent()).getPermission(),
                new FsPermission(tablePerms[i]));
            Assert.assertEquals("File permissions of table " + tableNames[i] + " is not correct",
                fs.getFileStatus(partitionFile.getParent().getParent()).getPermission(),
                new FsPermission(tablePerms[i]));

        }
        LOG.info("File permissions verified");
    }

    /**
     * Create a input file for map
     *
     * @return absolute path of the file.
     * @throws IOException if any error encountered
     */
    private Path createInputFile() throws IOException {
        Path f = new Path(workDir + "/MultiTableInput.txt");
        FileSystem fs = FileSystem.get(mrConf);
        if (fs.exists(f)) {
            fs.delete(f, true);
        }
        OutputStream out = fs.create(f);
        for (int i = 0; i < 3; i++) {
            out.write("a,a\n".getBytes());
        }
        out.close();
        return f;
    }

    /**
     * Method to fetch table data
     *
     * @param table table name
     * @param database database
     * @return list of columns in comma seperated way
     * @throws Exception if any error occurs
     */
    private List<String> getTableData(String table, String database) throws Exception {
        HiveConf conf = new HiveConf();
        conf.addResource("hive-site.xml");
        ArrayList<String> results = new ArrayList<String>();
        ArrayList<String> temp = new ArrayList<String>();
        Hive hive = Hive.get(conf);
        org.apache.hadoop.hive.ql.metadata.Table tbl = hive.getTable(database, table);
        FetchWork work;
        if (!tbl.getPartCols().isEmpty()) {
            List<Partition> partitions = hive.getPartitions(tbl);
            List<PartitionDesc> partDesc = new ArrayList<PartitionDesc>();
            List<String> partLocs = new ArrayList<String>();
            for (Partition part : partitions) {
                partLocs.add(part.getLocation());
                partDesc.add(Utilities.getPartitionDesc(part));
            }
            work = new FetchWork(partLocs, partDesc, Utilities.getTableDesc(tbl));
            work.setLimit(100);
        } else {
            work = new FetchWork(tbl.getDataLocation().toString(), Utilities.getTableDesc(tbl));
        }
        FetchTask task = new FetchTask();
        task.setWork(work);
        task.initialize(conf, null, null);
        task.fetch(temp);
        for (String str : temp) {
            results.add(str.replace("\t", ","));
        }
        return results;
    }

    private static class MyMapper extends
        Mapper<LongWritable, Text, BytesWritable, HCatRecord> {

        private int i = 0;

        @Override
        protected void map(LongWritable key, Text value, Context context)
            throws IOException, InterruptedException {
            HCatRecord record = null;
            String[] splits = value.toString().split(",");
            switch (i) {
            case 0:
                record = new DefaultHCatRecord(2);
                record.set(0, splits[0]);
                record.set(1, splits[1]);
                break;
            case 1:
                record = new DefaultHCatRecord(1);
                record.set(0, splits[0]);
                break;
            case 2:
                record = new DefaultHCatRecord(3);
                record.set(0, splits[0]);
                record.set(1, splits[1]);
                record.set(2, "extra");
                break;
            default:
                Assert.fail("This should not happen!!!!!");
            }
            MultiOutputFormat.write(tableNames[i], null, record, context);
            i++;
        }
    }
}
