package ${packageName}.service.block.impl;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import ${packageName}.mapper.block.${InstanceClassName}Mapper;
import ${packageName}.service.block.I${InstanceClassName}Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class ${InstanceClassName}ServiceImpl implements I${InstanceClassName}Service
{
    @Autowired
    private ${InstanceClassName}Mapper ${instanceClassName}Mapper;

    @Override
    public Map<String, Object> loadData()
    {
        Map<String, Object> params = new LinkedHashMap<String, Object>();
#foreach($parameter in $chartQuery.parameters)
        params.put("${parameter.name}", ${parameter.javaLiteral});
#end
        putDateRange(params);

        List<Map<String, Object>> rows = ${instanceClassName}Mapper.selectData(params);
        List<Map<String, Object>> dimensions = new ArrayList<Map<String, Object>>();
        List<Map<String, Object>> series = new ArrayList<Map<String, Object>>();
        Map<String, Object> summary = new LinkedHashMap<String, Object>();

#if($chartQuery.metricOnly)
        Object value = rows.isEmpty() ? null : rows.get(0).get(${chartMetrics.get(0).aliasLiteral});
        summary.put("value", value);
        summary.put("count", Integer.valueOf(rows.size()));
#else
#foreach($metric in $chartMetrics)
        series.add(seriesItem(${metric.labelLiteral}, ${metric.aliasLiteral}));
#end
        for (Map<String, Object> row : rows)
        {
            Map<String, Object> dimension = new LinkedHashMap<String, Object>();
            dimension.put("label", row.get("dimensionKey"));
            dimension.put("value", row.get("dimensionKey"));
            dimensions.add(dimension);
#foreach($metric in $chartMetrics)
            appendSeriesValue(series, ${foreach.index}, row.get(${metric.aliasLiteral}));
#end
        }
        summary.put("count", Integer.valueOf(rows.size()));
#end

        Map<String, Object> result = new LinkedHashMap<String, Object>();
        result.put("dimensions", dimensions);
        result.put("series", series);
        result.put("summary", summary);
        return result;
    }

    private Map<String, Object> seriesItem(String name, String alias)
    {
        Map<String, Object> item = new LinkedHashMap<String, Object>();
        item.put("name", name);
        item.put("alias", alias);
        item.put("values", new ArrayList<Object>());
        return item;
    }

    @SuppressWarnings("unchecked")
    private void appendSeriesValue(List<Map<String, Object>> series, int index, Object value)
    {
        ((List<Object>) series.get(index).get("values")).add(value);
    }

    private void putDateRange(Map<String, Object> params)
    {
#if($chartQuery.dateRange)
        LocalDate today = LocalDate.now();
#if($chartQuery.dateRange.preset == "today")
        params.put("dateStart", today.atStartOfDay());
        params.put("dateEnd", today.plusDays(1).atStartOfDay());
#elseif($chartQuery.dateRange.preset == "last_7_days")
        params.put("dateStart", today.minusDays(6).atStartOfDay());
        params.put("dateEnd", today.plusDays(1).atStartOfDay());
#elseif($chartQuery.dateRange.preset == "last_30_days")
        params.put("dateStart", today.minusDays(29).atStartOfDay());
        params.put("dateEnd", today.plusDays(1).atStartOfDay());
#elseif($chartQuery.dateRange.preset == "this_month")
        params.put("dateStart", today.withDayOfMonth(1).atStartOfDay());
        params.put("dateEnd", today.withDayOfMonth(1).plusMonths(1).atStartOfDay());
#elseif($chartQuery.dateRange.preset == "this_year")
        params.put("dateStart", today.withDayOfYear(1).atStartOfDay());
        params.put("dateEnd", today.withDayOfYear(1).plusYears(1).atStartOfDay());
#else
        params.put("dateStart", LocalDate.parse(${chartDateStartLiteral}).atStartOfDay());
        params.put("dateEnd", LocalDate.parse(${chartDateEndLiteral}).plusDays(1).atStartOfDay());
#end
#end
    }
}
