package mobvista.dmp.datasource.dm.mapreduce;

import mobvista.dmp.common.CommonMapReduce;
import mobvista.dmp.common.CommonMapper;
import mobvista.dmp.common.CommonReducer;
import mobvista.dmp.common.InstallTotalReducer;
import mobvista.dmp.util.MRUtils;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.compress.GzipCodec;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.codehaus.jackson.map.ObjectMapper;

import java.io.IOException;
import java.util.List;

/**
 * author: houying
 * date  : 17-3-14
 * desc  :
 * 此MR负责处理多个数据来源，生成安装列表的other分区，由于该分区数据来源复杂，输入和输出路径由脚本调用时通过-D参数制定
 * 为了是该MR处理逻辑单一，故统一规定所有输入路径的数据应满足如下格式：
 * device_id \t device_type \t platform \t package_list
 * 其中package_list是json数组格式，e.g. ["com.xxxx.yyyy", "org.aaaa.bbbb", ...]
 */
public class DmInstallListOtherMR extends CommonMapReduce {
    public DmInstallListOtherMR(String name, Class<? extends Mapper> mapperClass,
            Class<? extends Reducer> reducerClass) {
        super(name, mapperClass, reducerClass);
    }

    public static class InstallListOtherMapper extends CommonMapper {
        private String date;
        private ObjectMapper objectMapper;
        @Override
        protected void setup(Context context) throws IOException, InterruptedException {
            date = context.getConfiguration().get("task.date");
            objectMapper = new ObjectMapper();
        }
        @Override
        protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
            String line = value.toString();
            String[] array = MRUtils.SPLITTER.split(line);
            if (array.length != 4 ) {
                return;
            }
            outKey.set(MRUtils.JOINER.join(array[0], array[1], array[2]));
            if (array[3].contains("package_name")) { //install_list
                outValue.set(array[3]);
                context.write(outKey, outValue);
            } else { //other data source
                List<String> pkgs = objectMapper.readValue(array[3], List.class);
                for (String pkg: pkgs) {
                    outValue.set(MRUtils.JOINER.join(pkg, date));
                    context.write(outKey, outValue);
                }
            }
        }
    }

    @Override
    protected void otherSetting(Job job, String[] args) throws Exception {
        FileOutputFormat.setCompressOutput(job, true);
        FileOutputFormat.setOutputCompressorClass(job, GzipCodec.class);
    }

    public static void main(String[] args) throws Exception {
        start(new DmInstallListOtherMR("dm_install_list_other", InstallListOtherMapper.class, InstallTotalReducer.class), args);
    }
}
