/*
 * 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.pig.test.pigmix.datagen;

import java.io.*;
import java.lang.SecurityException;
import java.text.ParseException;
import java.util.*;

import sdsu.algorithms.data.Zipf;

import org.apache.pig.backend.hadoop.executionengine.mapReduceLayer.MRConfiguration;
import org.apache.pig.tools.cmdline.CmdLineParser;

import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.conf.*;
import org.apache.hadoop.io.*;
import org.apache.hadoop.mapred.*;
import org.apache.hadoop.util.*;

/**
 * A tool to generate data for performance testing.
 */
public class DataGenerator extends Configured implements Tool {
    ColSpec[] colSpecs;
    long seed = -1;
    long numRows = -1;
    int numMappers = -1;
    String outputFile;
    String inFile;
    char separator = '\u0001' ;
    Random rand;

    private String[] mapkey = { "a", "b", "c", "d", "e", "f", "g", "h", "i",
        "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w",
        "x", "y", "z"};

    public static void main(String[] args) throws Exception {
        DataGenerator dg = new DataGenerator();
        try {
            ToolRunner.run(new Configuration(), dg, args);
           }catch(Exception e) {
            throw new IOException (e);
        }
        dg.go();
    }

    protected DataGenerator(long seed) {
        System.out.println("Using seed " + seed);
        rand = new Random(seed);
    }

    protected DataGenerator() {

    }

    protected DataGenerator(String[] args) {

    }

    public int run(String[] args) throws Exception {
        CmdLineParser opts = new CmdLineParser(args);
        opts.registerOpt('e', "seed", CmdLineParser.ValueExpected.REQUIRED);
        opts.registerOpt('f', "file", CmdLineParser.ValueExpected.REQUIRED);
        opts.registerOpt('r', "rows", CmdLineParser.ValueExpected.REQUIRED);
        opts.registerOpt('s', "separator", CmdLineParser.ValueExpected.REQUIRED);
        opts.registerOpt('i', "input", CmdLineParser.ValueExpected.REQUIRED);
        opts.registerOpt('m', "mappers", CmdLineParser.ValueExpected.OPTIONAL);

        char opt;
        try {
            while ((opt = opts.getNextOpt()) != CmdLineParser.EndOfOpts) {
                switch (opt) {
                case 'e':
                    seed = Long.valueOf(opts.getValStr());
                    break;

                case 'f':
                    outputFile = opts.getValStr();
                    break;

                case 'i':
                    inFile = opts.getValStr();
                    break;

                case 'r':
                    numRows = Long.valueOf(opts.getValStr());
                    break;

                case 's':
                    separator = opts.getValStr().charAt(0);
                    break;

                case 'm':
                    numMappers = Integer.valueOf(opts.getValStr());
                    break;

                default:
                    usage();
                    break;
                }
            }
        } catch (ParseException pe) {
            System.err.println("Couldn't parse the command line arguments, " +
                pe.getMessage());
            usage();
        }

        if (numRows < 1 && inFile == null) usage();

        if (numRows > 0 && inFile != null) usage();

        if (numMappers > 0 && seed != -1) usage();

        if (seed == -1){
            seed = System.currentTimeMillis();
        }

        String remainders[] = opts.getRemainingArgs();
        colSpecs = new ColSpec[remainders.length];
        for (int i = 0; i < remainders.length; i++) {
            colSpecs[i] = new ColSpec(remainders[i]);
        }
        System.err.println("Using seed " + seed);
        rand = new Random(seed);

        return 0;
    }

    private void go() throws IOException {
        long t1 = System.currentTimeMillis();
        if (numMappers <= 0) {
            System.out.println("Generate data in local mode.");
            goLocal();
        }else{
            System.out.println("Generate data in hadoop mode.");
            HadoopRunner runner = new HadoopRunner();
            runner.goHadoop();
        }

        long t2 = System.currentTimeMillis();
        System.out.println("Job is successful! It took " + (t2-t1)/1000 + " seconds.");
    }

    public void goLocal() throws IOException {

        PrintWriter out = null;
        try {
            out = new PrintWriter(outputFile);
        } catch (FileNotFoundException fnfe) {
            System.err.println("Could not find file " + outputFile +
                ", " + fnfe.getMessage());
            return;
        } catch (SecurityException se) {
            System.err.println("Could not write to file " + outputFile +
                ", " + se.getMessage());
            return;
        }

        BufferedReader in = null;
        if (inFile != null) {
            try {
                    in = new BufferedReader(new FileReader(inFile));
            } catch (FileNotFoundException fnfe) {
                System.err.println("Unable to find input file " + inFile);
                return;
            }
        }

        if (numRows > 0) {
            for (int i = 0; i < numRows; i++) {
                writeLine(out);
                out.println();
            }
        } else if (in != null) {
            String line;
            while ((line = in.readLine()) != null) {
                out.print(line);
                writeLine(out);
                out.println();
            }
        }
        out.close();
    }

    protected void writeLine(PrintWriter out) {
        for (int j = 0; j < colSpecs.length; j++) {
            if (j != 0) out.print(separator);
            // First, decide if it's going to be null
            if (rand.nextInt(100) < colSpecs[j].pctNull) {
                continue;
            }
            writeCol(colSpecs[j], out);
        }
    }

    private void writeCol(ColSpec colspec, PrintWriter out) {
        switch (colspec.datatype) {
        case INT:
            out.print(colspec.nextInt());
            break;

        case LONG:
            out.print(colspec.nextLong());
            break;

        case FLOAT:
            out.print(colspec.nextFloat());
            break;

        case DOUBLE:
            out.print(colspec.nextDouble());
            break;

        case STRING:
            out.print(colspec.nextString());
            break;

        case MAP:
            int len = rand.nextInt(20) + 6;
            for (int k = 0; k < len; k++) {
                if (k != 0) out.print('');
                out.print(mapkey[k] + '');
                out.print(colspec.gen.randomString());
            }
            break;

        case BAG:
            int numElements = rand.nextInt(5) + 5;
            for (int i = 0; i < numElements; i++) {
                if (i != 0) out.print('');
                switch(colspec.contained.datatype) {
                    case INT: out.print("i"); break;
                    case LONG: out.print("l"); break;
                    case FLOAT: out.print("f"); break;
                    case DOUBLE: out.print("d"); break;
                    case STRING: out.print("s"); break;
                    case MAP: out.print("m"); break;
                    case BAG: out.print("b"); break;
                    default: throw new RuntimeException("should never be here");
                }
                writeCol(colspec.contained, out);
            }
        }
    }

    private void usage() {
        System.err.println("Usage: datagen -rows numrows [options] colspec ...");
        System.err.println("\tOptions:");
        System.err.println("\t-e -seed seed value for random numbers");
        System.err.println("\t-f -file output file, default is stdout");
        System.err.println("\t-i -input input file, lines will be read from");
        System.err.println("\t\tthe file and additional columns appended.");
        System.err.println("\t\tMutually exclusive with -r.");
        System.err.println("\t-r -rows number of rows to output");
        System.err.println("\t-s -separator character, default is ^A");
        System.err.println("\t-m -number of mappers to run concurrently to generate data. " +
                "If not specified, DataGenerator runs locally. This option can NOT be used with -e.");
        System.err.println();
        System.err.print("\tcolspec: columntype:average_size:cardinality:");
        System.err.println("distribution_type:percent_null");
        System.err.println("\tcolumntype:");
        System.err.println("\t\ti = int");
        System.err.println("\t\tl = long");
        System.err.println("\t\tf = float");
        System.err.println("\t\td = double");
        System.err.println("\t\ts = string");
        System.err.println("\t\tm = map");
        System.err.println("\t\tbx = bag of x, where x is a columntype");
        System.err.println("\tdistribution_type:");
        System.err.println("\t\tu = uniform");
        System.err.println("\t\tz = zipf");

        throw new RuntimeException();
    }



    static enum Datatype { INT, LONG, FLOAT, DOUBLE, STRING, MAP, BAG };
    static enum DistributionType { UNIFORM, ZIPF };
    protected class ColSpec {
        String arg;
        Datatype datatype;
        DistributionType distype;
        int avgsz;
        int card;
        RandomGenerator gen;
        int pctNull;
        ColSpec contained;
        String mapfile;
        Map<Integer, Object> map;

        public ColSpec(String arg) {
            this.arg = arg;

            String[] parts = arg.split(":");
            if (parts.length != 5 && parts.length != 6) {
                System.err.println("Colspec [" + arg + "] format incorrect");
                usage();
            }

            switch (parts[0].charAt(0)) {
                case 'i': datatype = Datatype.INT; break;
                case 'l': datatype = Datatype.LONG; break;
                case 'f': datatype = Datatype.FLOAT; break;
                case 'd': datatype = Datatype.DOUBLE; break;
                case 's': datatype = Datatype.STRING; break;
                case 'm': datatype = Datatype.MAP; break;
                case 'b':
                    datatype = Datatype.BAG;
                    contained = new ColSpec(arg.substring(1));
                    return;
                default:
                    System.err.println("Don't know column type " +
                        parts[0].charAt(0));
                    usage();
                    break;
            }
            avgsz = Integer.valueOf(parts[1]);
            card = Integer.valueOf(parts[2]);
            switch (parts[3].charAt(0)) {
                case 'u':
                    gen = new UniformRandomGenerator(avgsz, card);
                    distype = DistributionType.UNIFORM;
                    break;

                case 'z':
                    gen = new ZipfRandomGenerator(avgsz, card);
                    distype = DistributionType.ZIPF;
                    break;

                default:
                    System.err.println("Don't know generator type " +
                        parts[3].charAt(0));
                    usage();
                    break;
            }

            pctNull = Integer.valueOf(parts[4]);
            if (pctNull > 100) {
                System.err.println("Percentage null must be between 0-100, "
                    + "you gave" + pctNull);
                usage();
            }
            contained = null;

            // if config has 6 columns, the last col is the file name
            // of the mapping file from random number to field value
            if (parts.length == 6) {
                mapfile = parts[5];
                gen.hasMapFile = true;
            }

            map = new HashMap<Integer, Object>();
        }

        public int nextInt() {
            return gen.nextInt(map);
        }

        public long nextLong() {
            return gen.nextInt(map);
        }

        public double nextDouble() {
            return gen.nextDouble(map);
        }

        public float nextFloat() {
            return gen.nextFloat(map);
        }

        public String nextString() {
            return gen.nextString(map);
        }
    }

    abstract class RandomGenerator {

        protected int avgsz;
        protected boolean hasMapFile; // indicating whether a map file from
                                      // random number to the field value is pre-defined

        abstract public int nextInt(Map<Integer, Object> map);
        abstract public long nextLong(Map<Integer, Object> map);
        abstract public float nextFloat(Map<Integer, Object> map);
        abstract public double nextDouble(Map<Integer, Object> map);
        abstract public String nextString(Map<Integer, Object> map);

        public String randomString() {
            int var = (int)((double)avgsz * 0.3);
            StringBuffer sb = new StringBuffer(avgsz + var);
            if (var < 1) var = 1;
            int len = rand.nextInt(2 * var) + avgsz - var;
            for (int i = 0; i < len; i++) {
                int n = rand.nextInt(122 - 65) + 65;
                sb.append(Character.toChars(n));
            }
            return sb.toString();
        }

        public float randomFloat() {
            return rand.nextFloat() * rand.nextInt();
        }

        public double randomDouble() {
            return rand.nextDouble() * rand.nextInt();
        }
    }

    class UniformRandomGenerator extends RandomGenerator {
        int card;

        public UniformRandomGenerator(int a, int c) {
            avgsz = a;
            card = c;
        }

        public int nextInt(Map<Integer, Object> map) {
            return rand.nextInt(card);
        }

        public long nextLong(Map<Integer, Object> map) {
            return rand.nextLong() % card;
        }

        public float nextFloat(Map<Integer, Object> map) {
            int seed = rand.nextInt(card);
            Float f = (Float)map.get(seed);
            if (f == null) {
                if (!hasMapFile) {
                    f = randomFloat();
                    map.put(seed, f);
                }else{
                    throw new IllegalStateException("Number " + seed + " is not found in map file");
                }
            }
            return f;
        }

        public double nextDouble(Map<Integer, Object> map) {
            int seed = rand.nextInt(card);
            Double d = (Double)map.get(seed);
            if (d == null) {
                if (!hasMapFile) {
                    d = randomDouble();
                    map.put(seed, d);
                }else{
                    throw new IllegalStateException("Number " + seed + " is not found in map file");
                }
            }
            return d;
        }

        public String nextString(Map<Integer, Object> map) {
            int seed = rand.nextInt(card);
            String s = (String)map.get(seed);
            if (s == null) {
                if (!hasMapFile) {
                    s = randomString();
                    map.put(seed, s);
                }else{
                    throw new IllegalStateException("Number " + seed + " is not found in map file");
                }
            }
            return s;
        }

    }

    class ZipfRandomGenerator extends RandomGenerator {
        Zipf z;

        public ZipfRandomGenerator(int a, int c) {
            avgsz = a;
            z = new Zipf(c);
        }


        // the Zipf library returns a random number [1..cardinality], so we substract by 1
        // to get [0..cardinality)
        // the randome number returned by zipf library is an integer, but converted into double
        private double next() {
            return z.nextElement()-1;
        }

        public int nextInt(Map<Integer, Object> map) {
            return (int)next();
        }

        public long nextLong(Map<Integer, Object> map) {
            return (long)next();
        }

        public float nextFloat(Map<Integer, Object> map) {
            int seed = (int)next();
            Float d = (Float)map.get(seed);
            if (d == null) {
                if (!hasMapFile) {
                    d = randomFloat();
                    map.put(seed, d);
                }else{
                    throw new IllegalStateException("Number " + seed + " is not found in map file");
                }
            }
            return d;
        }

        public double nextDouble(Map<Integer, Object> map) {
             int seed = (int)next();
             Double d = (Double)map.get(seed);
             if (d == null) {
                 if (!hasMapFile) {
                     d = randomDouble();
                     map.put(seed, d);
                 }else{
                     throw new IllegalStateException("Number " + seed + " is not found in map file");
                 }
             }
             return d;
        }

        public String nextString(Map<Integer, Object> map) {
            int seed = (int)next();
            String s = (String)map.get(seed);
            if (s == null) {
                if (!hasMapFile) {
                    s = randomString();
                    map.put(seed, s);
                }else{
                    throw new IllegalStateException("Number " + seed + " is not found in map file");
                }
            }
            return s;
        }
    }

    //  launch hadoop job
    class HadoopRunner {
        Random r;
        FileSystem fs;
        Path tmpHome;

        public HadoopRunner() {
            r = new Random();
        }

        public void goHadoop() throws IOException {
            // Configuration processed by ToolRunner
            Configuration conf = getConf();

            // Create a JobConf using the processed conf
            JobConf job = new JobConf(conf);
            fs = FileSystem.get(job);

            tmpHome = createTempDir(null);

            String config = genMapFiles().toUri().getRawPath();
            // set config properties into job conf
            job.set("fieldconfig", config);
            job.set("separator", String.valueOf((int)separator));


            job.setJobName("data-gen");
            job.setNumMapTasks(numMappers);
            job.setNumReduceTasks(0);
            job.setMapperClass(DataGenMapper.class);
            job.setJarByClass(DataGenMapper.class);

            // if inFile is specified, use it as input
            if (inFile != null) {
                FileInputFormat.setInputPaths(job, inFile);
                job.set("hasinput", "true");
           } else {
               job.set("hasinput", "false");
               Path input = genInputFiles();
               FileInputFormat.setInputPaths(job, input);
           }
           FileOutputFormat.setOutputPath(job, new Path(outputFile));

            // Submit the job, then poll for progress until the job is complete
            System.out.println("Submit hadoop job...");
            RunningJob j = JobClient.runJob(job);
            if (!j.isSuccessful()) {
                throw new IOException("Job failed");
            }

            if (fs.exists(tmpHome)) {
                fs.delete(tmpHome, true);
            }
         }

         private Path genInputFiles() throws IOException {
             long avgRows = numRows/numMappers;

             // create a temp directory as mappers input
             Path input = createTempDir(tmpHome);
             System.out.println("Generating input files into " + input.toString());

             long rowsLeft = numRows;

             // create one input file per mapper, which contains
             // the number of rows
             for(int i=0; i<numMappers; i++) {
                 Object[] tmp = createTempFile(input, false);
                 PrintWriter pw = new PrintWriter((OutputStream)tmp[1]);

                 if (i < numMappers-1) {
                     pw.println(avgRows);
                 }else{
                     // last mapper takes all the rows left
                     pw.println(rowsLeft);
                 }

                 pw.close();
                 rowsLeft -= avgRows;
             }

             return input;
         }

        // generate map files for all the fields that need to pre-generate map files
        // return a config file which contains config info for each field, including
        // the path to their map file
         private Path genMapFiles() throws IOException {
             Object[] tmp = createTempFile(tmpHome, false);

             System.out.println("Generating column config file in " + tmp[0].toString());
             PrintWriter pw = new PrintWriter((OutputStream)tmp[1]);
             for(int i=0; i<colSpecs.length; i++) {
                 DataGenerator.Datatype datatype = colSpecs[i].datatype;
                 pw.print(colSpecs[i].arg);

                 if ( datatype == DataGenerator.Datatype.FLOAT || datatype == DataGenerator.Datatype.DOUBLE ||
                         datatype == DataGenerator.Datatype.STRING)      {
                     Path p = genMapFile(colSpecs[i]);
                     pw.print(':');
                     pw.print(p.toUri().getRawPath());
                 }

                 pw.println();
             }

             pw.close();

             return (Path)tmp[0];
         }

         // genereate a map file between random number to field value
         // return the path of the map file
         private Path genMapFile(DataGenerator.ColSpec col) throws IOException {
             int card = col.card;
             Object[] tmp = createTempFile(tmpHome, false);

             System.out.println("Generating mapping file for column " + col.arg + " into " + tmp[0].toString());
             PrintWriter pw = new PrintWriter((OutputStream)tmp[1]);
             HashSet<Object> hash = new HashSet<Object>(card);
             for(int i=0; i<card; i++) {
                 pw.print(i);
                 pw.print("\t");
                 Object next = null;
                 do {
                     if (col.datatype == DataGenerator.Datatype.DOUBLE) {
                         next = col.gen.randomDouble();
                     }else if (col.datatype == DataGenerator.Datatype.FLOAT) {
                         next = col.gen.randomFloat();
                     }else if (col.datatype == DataGenerator.Datatype.STRING) {
                         next = col.gen.randomString();
                     }
                 }while(hash.contains(next));

                 hash.add(next);

                 pw.println(next);

                 if ( (i>0 && i%300000 == 0) || i == card-1 ) {
                     System.out.println("processed " + i*100/card + "%." );
                     pw.flush();
                 }
             }

             pw.close();

             return (Path)tmp[0];

         }

         private Path createTempDir(Path parentDir) throws IOException {
             Object[] obj = createTempFile(parentDir, true);
             return (Path)obj[0];
         }

         private Object[] createTempFile(Path parentDir, boolean isDir) throws IOException {
             Path tmp_home = parentDir;

             if (tmp_home == null) {
                 tmp_home = new Path(fs.getHomeDirectory(), "tmp");
             }

             if (!fs.exists(tmp_home)) {
                 fs.mkdirs(tmp_home);
             }

             int id = r.nextInt();
             Path f = new Path(tmp_home, "tmp" + id);
             while (fs.exists(f)) {
                 id = r.nextInt();
                 f = new Path(tmp_home, "tmp" + id);
             }

             // return a 2-element array. first element is PATH,
             // second element is OutputStream
             Object[] r = new Object[2];
             r[0] = f;
             if (!isDir) {
                 r[1] = fs.create(f);
             }else{
                 fs.mkdirs(f);
             }

             return r;
         }
    }

    public static class DataGenMapper extends MapReduceBase implements Mapper<LongWritable, Text, String, String> {
         private JobConf jobConf;
         private DataGenerator dg;
         private boolean hasInput;

         public void configure(JobConf jobconf) {
             this.jobConf = jobconf;

             int id = Integer.parseInt(jobconf.get(MRConfiguration.TASK_PARTITION));
             long time = System.currentTimeMillis() - id*3600*24*1000;

             dg = new DataGenerator( ((time-id*3600*24*1000) | (id << 48)));

             dg.separator = (char)Integer.parseInt(jobConf.get("separator"));

             if (jobConf.get("hasinput").equals("true")) {
                 hasInput = true;
             }

             String config = jobConf.get("fieldconfig");

             try {
                 FileSystem fs = FileSystem.get(jobconf);

                 // load in config file for each column
                 BufferedReader reader = new BufferedReader(new InputStreamReader(fs.open(new Path(config))));
                 String line = null;
                 List<DataGenerator.ColSpec> cols = new ArrayList<DataGenerator.ColSpec>();
                 while((line = reader.readLine()) != null) {
                     cols.add(dg.new ColSpec(line));
                 }
                 reader.close();
                 dg.colSpecs = cols.toArray(new DataGenerator.ColSpec[0]);

                 // load in mapping files
                 for(int i=0; i<dg.colSpecs.length; i++) {
                     DataGenerator.ColSpec col = dg.colSpecs[i];
                     if (col.mapfile != null) {
                         reader = new BufferedReader(new InputStreamReader(fs.open(new Path(col.mapfile))));
                         Map<Integer, Object> map = dg.colSpecs[i].map;
                         while((line = reader.readLine()) != null) {
                             String[] fields = line.split("\t");
                             int key = Integer.parseInt(fields[0]);
                             if (col.datatype == DataGenerator.Datatype.DOUBLE) {
                                 map.put(key, Double.parseDouble(fields[1]));
                             }else if (col.datatype == DataGenerator.Datatype.FLOAT) {
                                 map.put(key, Float.parseFloat(fields[1]));
                             }else {
                                 map.put(key, fields[1]);
                             }
                         }

                         reader.close();
                     }
                 }
             }catch(IOException e) {
                 throw new RuntimeException("Failed to load config file. " + e);
             }
         }

         public void map(LongWritable key, Text value, OutputCollector<String, String> output, Reporter reporter) throws IOException {
             int intialsz = dg.colSpecs.length * 50;

             if (!hasInput) {
                 long numRows = Long.parseLong(value.toString().trim());
                  dg.numRows = numRows;

                  for (int i = 0; i < numRows; i++) {
                      StringWriter str = new StringWriter(intialsz);
                      PrintWriter pw = new PrintWriter(str);
                      dg.writeLine(pw);
                      output.collect(null, str.toString());

                      if ((i+1) % 10000 == 0) {
                          reporter.progress();
                          reporter.setStatus("" + (i+1) + " tuples generated.");
                      }
                  }
             } else {
                 StringWriter str = new StringWriter(intialsz);
                 PrintWriter pw = new PrintWriter(str);
                 pw.write(value.toString());
                 dg.writeLine(pw);
                 output.collect(null, str.toString());
             }
         }
     }
}

