package com.lanyuanxiaoyao.service.web.controller;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.lanyuanxiaoyao.service.configuration.entity.AmisResponse;
import com.lanyuanxiaoyao.service.configuration.entity.yarn.YarnApplication;
import com.lanyuanxiaoyao.service.configuration.entity.yarn.YarnQueue;
import com.lanyuanxiaoyao.service.forest.service.YarnService;
import com.lanyuanxiaoyao.service.web.entity.YarnApplicationVO;
import com.lanyuanxiaoyao.service.web.utils.ComparatorUtil;
import java.util.Comparator;
import java.util.Map;
import java.util.function.Function;
import org.eclipse.collections.api.factory.Lists;
import org.eclipse.collections.api.factory.Maps;
import org.eclipse.collections.api.list.ImmutableList;
import org.eclipse.collections.api.map.ImmutableMap;

/**
 * 放一些 Controller 的辅助方法
 *
 * @author lanyuanxiaoyao
 * @date 2023-04-21
 */
public class BaseController {
    private static final int SUCCESS_STATUS = 0;
    private static final String SUCCESS_MESSAGE = "OK";
    private static final ImmutableMap<String, Function<YarnApplication, Long>> SORT_MAP = Maps.immutable.of(
            "startedTime",
            YarnApplication::getStartedTime,
            "finishedTime",
            YarnApplication::getFinishedTime
    );

    protected AmisResponse responseData(Map<String, Object> data) {
        return AmisResponse.builder()
                .status(SUCCESS_STATUS)
                .message(SUCCESS_MESSAGE)
                .data(data)
                .build();
    }

    protected AmisResponse responseDetail(Object detail) {
        return AmisResponse.builder()
                .status(SUCCESS_STATUS)
                .message(SUCCESS_MESSAGE)
                .data(MapUtil.<String, Object>builder()
                        .put("detail", detail)
                        .build())
                .build();
    }

    protected AmisResponse responseCrudData(Iterable<?> data) {
        return AmisResponse.builder()
                .status(SUCCESS_STATUS)
                .message(SUCCESS_MESSAGE)
                .data(MapUtil.<String, Object>builder()
                        .put("items", data)
                        .build())
                .build();
    }

    protected AmisResponse responseCrudData(Iterable<?> data, Integer total) {
        return responseCrudData(data, Integer.toUnsignedLong(total));
    }

    protected AmisResponse responseCrudData(Iterable<?> data, Long total) {
        return AmisResponse.builder()
                .status(SUCCESS_STATUS)
                .message(SUCCESS_MESSAGE)
                .data(MapUtil.<String, Object>builder()
                        .put("items", data)
                        .put("total", total)
                        .build())
                .build();
    }

    protected AmisResponse jobList(
            YarnService yarnService,
            Integer page,
            Integer count,
            String order,
            String direction,
            String filterState,
            String filterFinalStatus,
            String searchId,
            String searchName,
            Boolean precise
    ) {
        boolean isFilterState = StrUtil.isNotBlank(filterState);
        boolean isFilterFinalStatus = StrUtil.isNotBlank(filterFinalStatus);
        boolean isSearchId = StrUtil.isNotBlank(searchId);
        boolean isSearchName = StrUtil.isNotBlank(searchName);
        Comparator<YarnApplication> comparator = ComparatorUtil.longComparator(order, direction, SORT_MAP);
        ImmutableList<YarnApplication> applications = yarnService.jobList()
                .select(app -> !isFilterState || ObjectUtil.contains(filterState, app.getState()))
                .select(app -> !isFilterFinalStatus || ObjectUtil.contains(filterFinalStatus, app.getFinalStatus()))
                .select(app -> !isSearchId || (precise ? StrUtil.equals(app.getId(), searchId) : StrUtil.contains(app.getId(), searchId)))
                .select(app -> !isSearchName || (precise ? StrUtil.equals(app.getName(), searchName) : StrUtil.contains(app.getName(), searchName)))
                .toSortedList(comparator)
                .toImmutable();
        int running = applications.count(app -> ObjectUtil.equal(app.getState(), "RUNNING"));
        int unRunning = applications.count(app -> ObjectUtil.notEqual(app.getState(), "RUNNING"));
        ImmutableList<YarnApplicationVO> result = applications
                .drop(Math.max(page - 1, 0) * count)
                .take(count)
                .collect(YarnApplicationVO::new);
        return responseCrudData(result, applications.size())
                .withData("running", running)
                .withData("unRunning", unRunning);
    }

    protected AmisResponse queueList(YarnService yarnService, String names) {
        boolean isFilterNames = StrUtil.isNotBlank(names);
        ImmutableList<String> filterNames = Lists.immutable.of(names.split(","));
        ImmutableList<YarnQueue> queues = yarnService.queueList();
        ImmutableList<YarnQueue> result = queues.select(queue -> !isFilterNames || filterNames.anySatisfy(n -> StrUtil.equals(queue.getQueueName(), n)));
        return responseCrudData(result, result.size())
                .withData("queueNames", queues.collect(YarnQueue::getQueueName))
                .withData("cluster", yarnService.cluster());
    }

    protected AmisResponse queueNames(YarnService yarnService) {
        return responseData(MapUtil.of("queueNames", yarnService.queueList().collect(YarnQueue::getQueueName)));
    }

    protected AmisResponse cluster(YarnService yarnService) {
        return responseData(MapUtil.of("cluster", yarnService.cluster()));
    }
}
