package com.sinewang.kiimate.status.core.fui;

import one.kii.kiimate.model.core.dai.IntensionDai;
import one.kii.kiimate.status.core.dai.InstanceDai;
import one.kii.kiimate.status.core.fui.InstanceTransformer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by WangYanJiong on 21/05/2017.
 */
@Component
public class DefaultInstanceTransformer implements InstanceTransformer {

    @Autowired
    private IntensionDai intensionDai;

    @Override
    public Map<String, Object> toTimedValue(List<InstanceDai.Instance> instancesList, String rootExtId) {
        Map<String, List<InstanceDai.Instance>> dict = dict(instancesList);
        Map<String, Object> map = parseTimed(rootExtId, dict);
        return map;
    }

    @Override
    public Map<String, Object> toRawValue(List<InstanceDai.Instance> instancesList, String rootExtId) {
        Map<String, List<InstanceDai.Instance>> dict = dict(instancesList);
        Map<String, Object> map = parseRaw(rootExtId, dict);
        return map;
    }

    private Map<String, Object> parseRaw(String extId, Map<String, List<InstanceDai.Instance>> dict) {
        List<IntensionDai.Intension> intensions = intensionDai.selectIntensionsByExtId(extId);
        Map<String, Object> result = new HashMap<>();
        for (IntensionDai.Intension intension : intensions) {
            if (intension.isSingle()) {
                if (intension.getRefExtId() != null) {
                    Map<String, Object> child = parseRaw(intension.getRefExtId(), dict);
                    if (!child.isEmpty()) {
                        result.put(intension.getField(), child);
                    }
                } else {
                    List<InstanceDai.Instance> instances = dict.get(intension.getField());
                    if (instances != null && !instances.isEmpty()) {
                        Object value = dict.get(intension.getField()).get(0).getValue();
                        if (value != null) {
                            result.put(intension.getField(), value);
                        }
                    }
                }
            } else {
                if (intension.getRefExtId() != null) {
                    Map<String, Object> child = parseTimed(intension.getRefExtId(), dict);
                    if (!child.isEmpty()) {
                        addComplexValueToList(result, intension, child);
                    }
                } else {
                    List<InstanceDai.Instance> instances = dict.get(intension.getField());
                    if (instances != null && !instances.isEmpty()) {
                        for (InstanceDai.Instance instance : instances) {
                            if (instance.getValue() != null) {
                                List values = (List) result.get(intension.getField());
                                if (values == null) {
                                    values = new ArrayList<>();
                                    result.put(intension.getField(), values);
                                }
                                values.add(instance.getValue());
                            }
                        }
                    }
                }

            }
        }
        return result;
    }


    private Map<String, Object> parseTimed(String extId, Map<String, List<InstanceDai.Instance>> dict) {
        List<IntensionDai.Intension> intensions = intensionDai.selectIntensionsByExtId(extId);
        Map<String, Object> result = new HashMap<>();
        for (IntensionDai.Intension intension : intensions) {
            if (intension.isSingle()) {
                if (intension.getRefExtId() != null) {
                    Map<String, Object> child = parseTimed(intension.getRefExtId(), dict);
                    if (!child.isEmpty()) {
                        result.put(intension.getField(), child);
                    }
                } else {
                    List<InstanceDai.Instance> instances = dict.get(intension.getField());
                    if (instances != null && !instances.isEmpty()) {
                        Object value = dict.get(intension.getField()).get(0).getValue();
                        if (value != null) {
                            TimedValue tv = new TimedValue();
                            tv.setValue(value);
                            tv.setTime(dict.get(intension.getField()).get(0).getBeginTime());
                            result.put(intension.getField(), tv);
                        }
                    }
                }
            } else {
                if (intension.getRefExtId() != null) {
                    Map<String, Object> child = parseTimed(intension.getRefExtId(), dict);
                    addComplexValueToList(result, intension, child);
                } else {
                    List<InstanceDai.Instance> instances = dict.get(intension.getField());
                    if (instances != null && !instances.isEmpty()) {
                        for (InstanceDai.Instance instance : instances) {
                            if (instance.getValue() != null) {
                                Object v = instance.getValue();
                                TimedValue tv = new TimedValue();
                                tv.setValue(v);
                                tv.setTime(instance.getBeginTime());
                                List values = (List) result.get(intension.getField());
                                if (values == null) {
                                    values = new ArrayList<>();
                                    result.put(intension.getField(), values);
                                }
                                values.add(tv);
                            }
                        }
                    }
                }

            }
        }
        return result;
    }


    private void addComplexValueToList(Map<String, Object> result, IntensionDai.Intension intension, Map<String, Object> child) {
        if (!child.isEmpty()) {
            List values = (List) result.get(intension.getField());
            if (values == null) {
                values = new ArrayList<>();
                result.put(intension.getField(), values);
            }
            values.add(child);
        }
    }

    private Map<String, List<InstanceDai.Instance>> dict(List<InstanceDai.Instance> instances) {
        Map<String, List<InstanceDai.Instance>> dict = new HashMap<>();
        for (InstanceDai.Instance instance : instances) {
            if (instance.getValueSetHash() == null) {
                List<InstanceDai.Instance> values = new ArrayList<>();
                values.add(instance);
                dict.put(instance.getField(), values);
            } else {
                List<InstanceDai.Instance> values = dict.get(instance.getField());
                if (values == null) {
                    values = new ArrayList<>();
                    dict.put(instance.getField(), values);
                }
                values.add(instance);
            }
        }
        return dict;
    }

}

@@ -5549,161 +5549,58 @@
     
-List values = (List) result.get(intension.getField());%0A                                if (values == null) %7B%0A                                    values =
+result.computeIfAbsent(instance.getField(), key -%3E
  new
@@ -5605,32 +5605,33 @@
 ew ArrayList%3C%3E()
+)
 ;%0A              
@@ -5644,35 +5644,52 @@
             
-   
+List values = (List)
  result.
 put(intensio
@@ -5668,34 +5668,34 @@
 = (List) result.
-pu
+ge
 t(intension.getF
@@ -5704,52 +5704,10 @@
 ld()
-, values);%0A                                %7D
+);
 %0A   
@@ -6816,141 +6816,56 @@
     
-List%3CInstanceDai.Instance%3E values = dict.get(instance.getField());%0A                if (values == null) %7B%0A                    values =
+dict.computeIfAbsent(instance.getField(), key -%3E
  new
@@ -6870,32 +6870,33 @@
 ew ArrayList%3C%3E()
+)
 ;%0A              
@@ -6893,35 +6893,67 @@
             
-   
+List%3CInstanceDai.Instance%3E values =
  dict.
-pu
+ge
 t(instance.g
@@ -6965,36 +6965,10 @@
 ld()
-, values);%0A                %7D
+);
 %0A   

use computeIfAbsent