package com.bocloud.ims.service.config;

import java.util.List;
import java.util.Set;

import javax.annotation.PostConstruct;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.entity.enums.ServerAssetCategory;
import com.bocloud.cmp.model.CloudVendorBean;
import com.bocloud.common.model.RequestContext;
import com.bocloud.common.model.RequestContext.Catalog;
import com.bocloud.common.utils.ListTool;
import com.bocloud.ims.entity.resource.CloudServer;
import com.bocloud.ims.entity.resource.CloudVendor;
import com.bocloud.ims.entity.resource.SnapshotTask;
import com.bocloud.ims.interfaces.scheduler.CloudVendorTaskService;
import com.bocloud.ims.interfaces.scheduler.ServerTimedTaskService;
import com.bocloud.ims.interfaces.scheduler.SnapshotTaskService;
import com.bocloud.ims.repository.resource.CloudServerRepository;
import com.bocloud.ims.repository.resource.CloudVendorRepository;
import com.bocloud.ims.repository.resource.SnapshotTaskRepository;
import com.bocloud.ims.service.scheduler.ScheduledTasksConstant;
import com.bocloud.service.core.CurrentService;

/**
 * 
 * @ClassName: SchedulingInitializingConfig.java
 * @Description:定时任务初始化任务
 *
 * @author: ymh
 * @date: 2021年3月16日 下午5:29:08
 */
@Component
public class SchedulingInitializingConfig {

    private static Logger logger = LoggerFactory.getLogger(SchedulingInitializingConfig.class);

    @Autowired
    private CloudVendorRepository cloudVendorRepository;
    @Autowired
    private CloudVendorTaskService cloudVendorTaskService;
    @Autowired
    private CurrentService service;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private ServerTimedTaskService serverTimedTaskService;
    @Autowired
    private DefaultSchedulingConfigurer defaultSchedulingConfigurer;
    @Autowired
    private ThreadPoolTaskExecutor taskExecutor;
    @Autowired
    private SnapshotTaskRepository snapshotTaskRepository;
    @Autowired
    private SnapshotTaskService snapshotTaskService;
    @Autowired
    private CloudServerRepository cloudServerRepository;

    public SchedulingInitializingConfig() {
        super();
    }

    @PostConstruct
    protected void initTask() {
        try {
            if (!service.isLeader()) {
                return;
            }
            // 设置云平台的定时任务
            this.cloudVendorTask();
            // X86服务器同步设置
            this.x86ServerTask();
            // 快照定时任务
            this.snapshotTask();
        } catch (Exception e) {
            logger.error("云平台定时同步 -> 初始化Error . " + e);
        }
    }

    /**
     * 用于集群时的容灾处理
     * 
     * @throws Exception
     */
    @Scheduled(cron = "${cloudvendor.sync.schedule:0 */1 * * * ?}")
    protected void syncVendorTask() throws Exception {
        if (!service.isLeader()) {
            defaultSchedulingConfigurer.clearTasks();
            return;
        }
        List<CloudVendor> cloudVendors = cloudVendorRepository.listAll();
        if (null == cloudVendors || cloudVendors.isEmpty()) {
        	defaultSchedulingConfigurer.clearTasks(ScheduledTasksConstant.CLOUD_VENDOR);
            return;
        }
		Set<String> taskIds = defaultSchedulingConfigurer.taskIds(ScheduledTasksConstant.CLOUD_VENDOR);
		for (CloudVendor cloudVendor : cloudVendors) {
            String syncCron = cloudVendor.getSyncCron();
            String taskId = ScheduledTasksConstant.CLOUD_VENDOR + cloudVendor.getUuid();
            taskIds.remove(taskId);
            if (StringUtils.isEmpty(syncCron)) {
                logger.warn("云平台【" + cloudVendor.getName() + "】没有定时任务，请注意及时调整！");
                continue;
            }
            if (!defaultSchedulingConfigurer.hasTask(taskId)) {
                cloudVendorTaskService.create(cloudVendor.getId(),
                    new RequestContext(Catalog.Manager, 1L, 0L, null, null));
                continue;
            }
            if (StringUtils.isNotEmpty(syncCron)
                && !syncCron.equalsIgnoreCase(defaultSchedulingConfigurer.getTaskCron(taskId))) {
                CloudVendorBean cloudVendorBean = new CloudVendorBean();
                cloudVendorBean.setId(cloudVendor.getId());
                cloudVendorBean.setSyncCron(cloudVendor.getSyncCron());
                cloudVendorTaskService.modify(cloudVendorBean, new RequestContext(Catalog.Manager, 1L, 0L, null, null));
            }
        }
		if (taskIds.size() > 0) {
			for (String taskId : taskIds) {
				if (!taskId.startsWith(ScheduledTasksConstant.CLOUD_VENDOR)) {
					continue;
				}
				defaultSchedulingConfigurer.cancelTriggerTask(taskId);
			}
		}
    }

    /**
     * 用于集群时的容灾处理
     * 
     * @throws Exception
     */
    @Scheduled(cron = "${cloudvendor.sync.schedule:0 */1 * * * ?}")
    protected void syncSnapshotTask() throws Exception {
        if (!service.isLeader()) {
            defaultSchedulingConfigurer.clearTasks();
            return;
        }
        Set<String> taskIds = defaultSchedulingConfigurer.taskIds(ScheduledTasksConstant.SNAPSHOT);
        List<SnapshotTask> snapshotTasks = snapshotTaskRepository.listByVendorId(null);
        if (ListTool.isEmpty(snapshotTasks)) {
        	defaultSchedulingConfigurer.clearTasks(ScheduledTasksConstant.SNAPSHOT);
            return;
        }
        for (SnapshotTask snapshotTask : snapshotTasks) {
            String syncCron = snapshotTask.getCron();
            if (StringUtils.isEmpty(syncCron)) {
                logger.warn("快照定时任务【" + snapshotTask.getName() + "】没有同步表达式，请注意及时调整！");
                continue;
            }
            Long serverId = snapshotTask.getServerId();
            CloudServer cloudServer = cloudServerRepository.query(serverId);
            if(null == cloudServer) {
                logger.info("定时快照任务对应云主机不存在！");
                snapshotTaskRepository.remove(snapshotTask.getId());
                continue;
            }
            String taskId = ScheduledTasksConstant.SNAPSHOT + snapshotTask.getTaskId();
            taskIds.remove(taskId);
            if (!defaultSchedulingConfigurer.hasTask(taskId)) {
                snapshotTaskService.create(snapshotTask.getTaskId(), new RequestContext(Catalog.Manager, 1L, 0L, null, null));
                continue;
            }
            if (StringUtils.isNotEmpty(syncCron)
                && !syncCron.equalsIgnoreCase(defaultSchedulingConfigurer.getTaskCron(taskId))) {
                snapshotTaskService.modify(snapshotTask.getTaskId(), new RequestContext(Catalog.Manager, 1L, 0L, null, null));
            }
        }
        if (taskIds.size() > 0) {
			for (String taskId : taskIds) {
				if (!taskId.startsWith(ScheduledTasksConstant.SNAPSHOT)) {
					continue;
				}
				defaultSchedulingConfigurer.cancelTriggerTask(taskId);
				System.out.println("删除定时任务 ： " + taskId);
			}
		}
    }

    /**
     * 用于集群时的容灾处理
     * 
     * @throws Exception
     */
    @Scheduled(cron = "${cloudvendor.sync.schedule:0 */1 * * * ?}")
    protected void syncServerTask() throws Exception {
        if (!service.isLeader()) {
            defaultSchedulingConfigurer.cancelTriggerTask(ServerAssetCategory.X86_SERVER.name());
            return;
        }
        // X86服务器的定时同步任务
        String cron = redisTemplate.opsForValue().get(ServerAssetCategory.X86_SERVER.name());
        // 如果定时表达式不为空 且当前服务中没有这个定时任务 则加入
        if (StringUtils.isNotEmpty(cron)) {
            if (!defaultSchedulingConfigurer.hasTask(ServerAssetCategory.X86_SERVER.name()) || !cron
                .equalsIgnoreCase(defaultSchedulingConfigurer.getTaskCron(ServerAssetCategory.X86_SERVER.name()))) {
                serverTimedTaskService.create(ServerAssetCategory.X86_SERVER.name(), cron,
                    new RequestContext(Catalog.Manager, 1L, 0L, null, null));
            }
        }
    }

    private void x86ServerTask() {
        taskExecutor.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    String cron = redisTemplate.opsForValue().get(ServerAssetCategory.X86_SERVER.name());
                    if (StringUtils.isNotEmpty(cron)) {
                        serverTimedTaskService.create(ServerAssetCategory.X86_SERVER.name(), cron,
                            new RequestContext(Catalog.Manager, 1L, 0L, null, null));
                    }
                } catch (Exception e) {
                    logger.error("X86_SERVER同步异常： " + e.getMessage());
                }
            }
        });
    }

    private void cloudVendorTask() {
        taskExecutor.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    List<CloudVendor> vendors = cloudVendorRepository.listAll();
                    for (CloudVendor vendor : vendors) {
                        if (StringUtils.isEmpty(vendor.getSyncCron())) {
                            logger.warn(vendor.getName() + "平台没有定时策略，请及时调整！");
                            continue;
                        }
                        cloudVendorTaskService.create(vendor.getId(),
                            new RequestContext(Catalog.Manager, 1L, 0L, null, null));
                    }
                } catch (Exception e) {
                    logger.error("平台定时同步异常： " + e.getMessage());
                }
            }
        });
    }

    private void snapshotTask() {
        taskExecutor.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    List<SnapshotTask> snapshotTasks = snapshotTaskRepository.listByVendorId(null);
                    for (SnapshotTask snapshotTask : snapshotTasks) {
                        if (StringUtils.isEmpty(snapshotTask.getCron())) {
                            logger.warn(snapshotTask.getName() + "定时快照任务没有同步表达式，请及时调整！");
                            continue;
                        }
                        snapshotTaskService.create(snapshotTask.getTaskId(),
                            new RequestContext(Catalog.Manager, 1L, 0L, null, null));
                    }
                } catch (Exception e) {
                    logger.error("平台定时同步异常： " + e.getMessage());
                }
            }
        });
    }
}
