package examples.dataloader;

import com.aliyun.odps.data.Record;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

public class RequestContextOffline {
    public Map<String, Object> featureMap = new HashMap<>();

    public void putUserFeature(Record record){
        setKVinMap(record, "machineinfo_brand", "string", "");
        setKVinMap(record, "machineinfo_model", "string", "");
        setKVinMap(record, "machineinfo_platform", "string","");
        setKVinMap(record, "machineinfo_system", "string","");

        setKVinMap(record, "u_1day_exp_cnt", "double", "cnt");
        setKVinMap(record, "u_1day_click_cnt", "double", "cnt");
        setKVinMap(record, "u_1day_share_cnt", "double", "cnt");
        setKVinMap(record, "u_1day_return_cnt", "double", "cnt");

        setKVinMap(record, "u_ctr_1day", "double", "rate");
        setKVinMap(record, "u_str_1day", "double", "rate");
        setKVinMap(record, "u_rov_1day", "double", "rate");
        setKVinMap(record, "u_ros_1day", "double", "rate");

        setKVinMap(record, "u_3day_exp_cnt", "double", "cnt");
        setKVinMap(record, "u_3day_click_cnt", "double", "cnt");
        setKVinMap(record, "u_3day_share_cnt", "double", "cnt");
        setKVinMap(record, "u_3day_return_cnt", "double", "cnt");

        setKVinMap(record, "u_ctr_3day", "double", "rate");
        setKVinMap(record, "u_str_3day", "double", "rate");
        setKVinMap(record, "u_rov_3day", "double", "rate");
        setKVinMap(record, "u_ros_3day", "double", "rate");
    }
    public void putItemFeature(Record record){
        // setKVinMap(record, "i_title_len", "double", "cnt");
        setKVinMap(record, "total_time", "double", "cnt");
        // setKVinMap(record, "i_days_since_upload", "double", "cnt");
        setKVinMap(record, "play_count_total", "double", "cnt");

        setKVinMap(record, "i_1day_exp_cnt", "double", "cnt");
        setKVinMap(record, "i_1day_click_cnt", "double", "cnt");
        setKVinMap(record, "i_1day_share_cnt", "double", "cnt");
        setKVinMap(record, "i_1day_return_cnt", "double", "cnt");

        setKVinMap(record, "i_ctr_1day", "double", "rate");
        setKVinMap(record, "i_str_1day", "double", "rate");
        setKVinMap(record, "i_rov_1day", "double", "rate");
        setKVinMap(record, "i_ros_1day", "double", "rate");

        setKVinMap(record, "i_3day_exp_cnt", "double", "cnt");
        setKVinMap(record, "i_3day_click_cnt", "double", "cnt");
        setKVinMap(record, "i_3day_share_cnt", "double", "cnt");
        setKVinMap(record, "i_3day_return_cnt", "double", "cnt");

        setKVinMap(record, "i_ctr_3day", "double", "rate");
        setKVinMap(record, "i_str_3day", "double", "rate");
        setKVinMap(record, "i_rov_3day", "double", "rate");
        setKVinMap(record, "i_ros_3day", "double", "rate");
    }

    public void putSceneFeature(Record record){
        setKVinMap(record, "ctx_week", "string", "");
        setKVinMap(record, "ctx_hour", "string", "");
        setKVinMap(record, "ctx_region", "string","");
        setKVinMap(record, "ctx_city", "string","");
    }
    public void setKVinMap(Record record, String key, String instance, String cntOrRate){
        if (!Arrays.stream(record.getColumns()).map(r-> r.getName()).collect(Collectors.toSet()).contains(key)){
            return;
        }
        String value;
        try{
            value = record.getString(key);
        }catch (Exception e){
            value = String.valueOf(record.getBigint(key));
        }

        if (value == null){
            return;
        }
        String ins = instance.toLowerCase();
        switch (ins){
            case "string":
                featureMap.put(key, value);
                return;
            case "double":
                if ("cnt".equals(cntOrRate)){
                    featureMap.put(key, String.valueOf(this.bucketRatioFeature(Double.valueOf(value))));
                }else if ("rate".equals(cntOrRate)){
                    featureMap.put(key, String.valueOf(this.ceilLog(Double.valueOf(value))));
                }
                return;
            case "int":
                return;
            case "long":
                return;
            default:
                return;
        }
    }


    public double ceilLog(Double key) {
        return Math.ceil(Math.log(key + 1.0));
    }

    public double bucketRatioFeature(Double key) {
        long bucket = Math.round(Math.log((key + 1.0) * 50.0));
        if (bucket > 50L) {
            bucket = 50L;
        }

        return (double)bucket;
    }
}
