package net.wicp.tams.duckula.ops.pages.devops;

import java.util.List;
import java.util.concurrent.CountDownLatch;

import org.apache.commons.collections.CollectionUtils;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.util.TextStreamResponse;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;

import lombok.extern.slf4j.Slf4j;
import net.wicp.tams.app.duckula.controller.bean.models.DevopsFlink;
import net.wicp.tams.app.duckula.controller.bean.models.DevopsFlinkExample;
import net.wicp.tams.app.duckula.controller.bean.models.DevopsFlinkExample.Criteria;
import net.wicp.tams.app.duckula.controller.config.constant.DevOpsType;
import net.wicp.tams.app.duckula.controller.dao.DevopsFlinkMapper;
import net.wicp.tams.common.Conf;
import net.wicp.tams.common.Result;
import net.wicp.tams.common.apiext.IOUtil;
import net.wicp.tams.common.apiext.StringUtil;
import net.wicp.tams.common.apiext.TimeAssist;
import net.wicp.tams.common.constant.PathType;
import net.wicp.tams.common.constant.dic.YesOrNo;
import net.wicp.tams.common.os.SSHAssit;
import net.wicp.tams.common.os.pool.SSHConnection;
import net.wicp.tams.common.thread.ThreadPool;
import net.wicp.tams.component.tools.TapestryAssist;
import net.wicp.tams.duckula.ops.pages.ParentPageBean;

@Slf4j
public class FlinkConfig extends ParentPageBean<DevopsFlink> {

	@Inject
	private DevopsFlinkMapper devopsFlinkMapper;

	@Override
	public void doSave(DevopsFlink t, boolean isInsert) {
		if (isInsert) {
			t.setIsInit(YesOrNo.no.name());
			t.setIsFree(YesOrNo.no.name());
			List<DevopsFlink> list = queryHostByCluster(t.getCluster());
			int lastindex = 0;
			if (CollectionUtils.isNotEmpty(list)) {
				String hostname = list.get(list.size() - 1).getHostname();
				String last = hostname.substring(hostname.length() - 1, hostname.length());
				lastindex = Integer.parseInt(last);
			}
			t.setHostname(String.format("prod-bigdata-flink%02d", ++lastindex));// 设置主机名
			devopsFlinkMapper.insert(t);
		} else {
			devopsFlinkMapper.updateByPrimaryKeySelective(t);
		}
	}

	@Override
	public void doDel(String id) {
		this.devopsFlinkMapper.deleteById(id);
	}

	@Override
	public BaseMapper<DevopsFlink> getBaseMapper() {
		return this.devopsFlinkMapper;
	}

	@Override
	public void packageQuery(DevopsFlink t, QueryWrapper<DevopsFlink> queryWrapper) {
		if (StringUtil.isNotNull(t.getName())) {
			queryWrapper.eq("name", t.getName());
		}
		if (StringUtil.isNotNull(t.getIsInit())) {
			queryWrapper.eq("is_init", t.getIsInit());
		}
	}

	// 不排序是以id顺序
	private List<DevopsFlink> queryHostByCluster(String cluster) {
		DevopsFlinkExample example = new DevopsFlinkExample();
		Criteria criteria = example.createCriteria();
		criteria.andClusterEqualTo(cluster);
		List<DevopsFlink> list = devopsFlinkMapper.selectByExample(example);

		return list;
	}

	/***
	 * 测试用后端调用
	 * 
	 * @return
	 */
	public TextStreamResponse onCheckHost() {
		final DevopsFlink devopsFlink = TapestryAssist.getBeanFromPage(DevopsFlink.class, requestGlobals);
		// 查询此集群下面的主机配置
		List<DevopsFlink> list = queryHostByCluster(devopsFlink.getCluster());
		StringBuffer checkparam = new StringBuffer();
		StringBuffer freeparam = new StringBuffer();
		for (int i = 0; i < list.size(); i++) {
			DevopsFlink flink = list.get(i);
			checkparam.append(String.format(" %s %s", flink.getIp(), flink.getHostname()));
			freeparam.append(String.format(" %s %s %s", flink.getRootUser(), flink.getHostname(), flink.getRootPwd()));
		}
		// 1、OSS下载
		String localPath = PathType.getPath(DevOpsType.flink.getCheckDownFile());
		// 1、登陆
		SSHConnection conn = SSHAssit.getConn(devopsFlink.getIp(), devopsFlink.getRootUser(), devopsFlink.getRootPwd());
		// String fileName = localPath.substring(localPath.lastIndexOf("/") + 1);
		String remoteDir = DevOpsType.flink.getRemoteDirCheckDir();
		conn.executeCommand("mkdir -p " + remoteDir);
		// conn.scpToDir(localPath,remoteDir , "0744");
		conn.scpDir(localPath, remoteDir, "0744", new String[] {}, new String[] {});
		// conn.scp(localPath, fileName, "~" + DevOpsType.flink.getRelaPathCheck(),
		// "0744");
		// check
		Result result = conn.executeCommand(String.format("sh %s %s",
				IOUtil.mergeFolderAndFilePath("~/", DevOpsType.flink.getRelaPathCheck()), checkparam.toString()));
		if (!result.isSuc()) {// 不成功
			log.info(result.getMessage());
			conn.close();
			return TapestryAssist.getTextStreamResponse(Result.getError(result.getMessage()));
		}
		devopsFlink.setIsInit(YesOrNo.yes.name());
		devopsFlinkMapper.updateByPrimaryKeySelective(devopsFlink);// 保存check结果
		list = queryHostByCluster(devopsFlink.getCluster());// 重新查一下数据库，因为有数据改变状态
		if (YesOrNo.yes.name().equals(devopsFlink.getNeedFree())) {
			boolean doFree = true;// 默认需要做
			for (DevopsFlink ele : list) {
				if (YesOrNo.no.name().equals(ele.getIsInit())) {
					doFree = false;
					break;
				}
			}
			if (doFree) {
				CountDownLatch countDownLatch = new CountDownLatch(list.size());
				// 三台机都做免密
				for (DevopsFlink devopsFlink2 : list) {
					ThreadPool.getDefaultPool().submit(new Runnable() {
						@Override
						public void run() {
							Conf.overProp("common.os.ssh.timeout", "30000");
							SSHConnection freeconn = SSHAssit.getConn(devopsFlink2.getIp(), 22,
									devopsFlink2.getRootUser(), devopsFlink2.getRootPwd(), 5 * 6000);
							try {
								// free，由于需要ssh到别的服务器，拿到到返回的日志，采用先做，重定向到~/flink/freelog，再查日志文件的方式完成
								Result freeRs = freeconn.executeCommand(String.format("sh %s %s &>~/flink/freelog",
										IOUtil.mergeFolderAndFilePath("~/",
												DevOpsType.flink.getRelaPath(DevOpsType.flink.getOtherparams()[0])),
										freeparam.toString()));

								TimeAssist.reDoWaitInit("flinkconfig-free");
								while (true) {
									try {
										boolean reDoWait = TimeAssist.reDoWait("flinkconfig-free", 9);// 9次512秒9分钟不到
										if (reDoWait) {
											break;
										}
										Result freeResult = freeconn.executeCommand("cat ~/flink/freelog");
										if (freeResult.isSuc()) {
											if (freeResult.getMessage().contains("执行免密操作结束")) {// 执行完了
												// 成功：ssh scripts run cmd SUCCESS
												boolean contains = freeResult.getMessage()
														.contains("ssh scripts run cmd ERROR");
												if (!contains) {// 成功
													// 保存
													devopsFlink2.setIsFree(YesOrNo.yes.name());
													devopsFlinkMapper.updateByPrimaryKeySelective(devopsFlink2);// 保存免密结果
												}
												break;
											}
										}
									} catch (Exception e) {
										e.printStackTrace();
									}
								}

							} finally {
								SSHAssit.close(freeconn);
								countDownLatch.countDown();
							}

						}
					});
				}
				try {
					countDownLatch.await();// 全部做完了就放
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
		return TapestryAssist.getTextStreamResponse(Result.getSuc());
	}

}
