package com.bocloud.ims.service.scheduler.scheduler;

import com.bocloud.cmp.entity.enums.CloudProvider;
import com.bocloud.common.utils.ListTool;
import com.bocloud.ims.common.utils.DateUtils;
import com.bocloud.ims.entity.resource.CloudServer;
import com.bocloud.ims.entity.resource.Cluster;
import com.bocloud.ims.entity.resource.ClusterUsage;
import com.bocloud.ims.entity.resource.Server;
import com.bocloud.ims.repository.resource.CloudServerRepository;
import com.bocloud.ims.repository.resource.ClusterRepository;
import com.bocloud.ims.repository.resource.ClusterUsageRepository;
import com.bocloud.ims.repository.resource.ServerRepository;
import com.bocloud.service.core.CurrentService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Component
public class ClusterUsageScheduler implements InitializingBean {

	private static Logger logger = LoggerFactory.getLogger(ClusterUsageScheduler.class);
	@Autowired
	private CurrentService currentService;
	@Autowired
	private ClusterRepository clusterRepository;
	@Autowired
	private ClusterUsageRepository clusterUsageRepository;
	@Autowired
	private ServerRepository serverRepository;
	@Autowired
	private CloudServerRepository cloudServerRepository;

	@Scheduled(cron = "${cluster.usage.scheduler:0 0 0 * * ?}")
	protected void usage() {
		if (!currentService.isLeader()) {
			return;
		}
		try {
			List<Cluster> clusters = clusterRepository.listByType(CloudProvider.VMWARE.name());
			if (ListTool.isEmpty(clusters)) {
				return;
			}
			for (Cluster cluster : clusters) {
				Long cpu = 0L;
				Long instance = 0L;
				Double mem = 0D;
				Double disk = 0D;
				int template = 0;
				List<Server> servers = serverRepository.listByCluster(cluster.getId());
				if (!ListTool.isEmpty(servers)) {
					for (Server server : servers) {
						List<CloudServer> cloudServers = cloudServerRepository.listByHid(server.getId());
						if (ListTool.isEmpty(cloudServers)) {
							continue;
						}
						for (CloudServer vm : cloudServers) {
							disk += null == vm.getDisk() ? 0 : vm.getDisk();
							if (vm.getIsTemplate()) {
								template++;
								continue;
							}
							cpu += null == vm.getCpu() ? 0 : vm.getCpu();
							mem += null == vm.getMemory() ? 0 : vm.getMemory().doubleValue();
						}
						instance += cloudServers.size();
					}
				}
				ClusterUsage usage = new ClusterUsage(cluster.getId(), cpu, mem, disk, instance - template,
						DateUtils.addDay(new Date(), -1));
				clusterUsageRepository.save(usage);
			}
		} catch (Exception e) {
			logger.error("stats cluster usage info error:", e);
		}
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		if (!currentService.isLeader()) {
			return;
		}
		try {
			List<ClusterUsage> clusterUsages = clusterUsageRepository.list(new ArrayList<>(), null);
			if (!ListTool.isEmpty(clusterUsages)) {
				return;
			}
			List<Cluster> clusters = clusterRepository.listByType(CloudProvider.VMWARE.name());
			if (ListTool.isEmpty(clusters)) {
				return;
			}
			for (Cluster cluster : clusters) {
				List<Server> servers = serverRepository.listByCluster(cluster.getId());
				if (ListTool.isEmpty(servers)) {
					continue;
				}
				List<CloudServer> list = new ArrayList<>();
				for (Server server : servers) {
					List<CloudServer> cloudServers = cloudServerRepository.listByHid(server.getId());
					if (!ListTool.isEmpty(cloudServers)) {
						list.addAll(cloudServers);
					}
				}
				if (ListTool.isEmpty(list)) {
					continue;
				}
				int i = 0;
				while (true) {
					List<CloudServer> vms = new ArrayList<>();
					String day = DateUtils.dateToString(DateUtils.addDay(new Date(), i), "yyyy-MM-dd") + " 00:00:00";
					for (CloudServer server : list) {
						if (server.getGmtCreate().getTime() < DateUtils.stringToDate(day, "yyyy-MM-dd").getTime()) {
							vms.add(server);
						}
					}
					if (vms.size() == 0) {
						break;
					}
					Long cpu = 0L;
					Double mem = 0D;
					Double disk = 0D;
					int tempalte = 0;
					for (CloudServer vm : vms) {
						disk += null == vm.getDisk() ? 0 : vm.getDisk();
						if (vm.getIsTemplate()) {
							tempalte++;
							continue;
						}
						cpu += null == vm.getCpu() ? 0 : vm.getCpu();
						mem += null == vm.getMemory() ? 0 : vm.getMemory().doubleValue();
					}
					Long instance = (long) vms.size() - tempalte;
					ClusterUsage usage = new ClusterUsage(cluster.getId(), cpu, mem, disk, instance, DateUtils.addDay(
							new Date(), i - 1));
					clusterUsageRepository.save(usage);
					i--;
					list.clear();
					list.addAll(vms);
				}
			}
		} catch (Exception e) {
			logger.error("stats cluster usage info error:", e);
		}
	}

}
