package com.bocloud.ims.booter.controller.resource.compute;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONValidator;
import com.bocloud.cmp.entity.enums.CloudProvider;
import com.bocloud.cmp.model.HostOperateModel;
import com.bocloud.cmp.model.SwitchModel;
import com.bocloud.cmp.model.sangfor.SangforIfacesModel;
import com.bocloud.common.annotations.Log;
import com.bocloud.common.enums.BoCloudService;
import com.bocloud.common.model.*;
import com.bocloud.common.utils.Common;
import com.bocloud.common.utils.JSONTools;
import com.bocloud.common.utils.ResultTools;
import com.bocloud.ims.entity.params.LabelParam;
import com.bocloud.ims.entity.params.ServerCreateParam;
import com.bocloud.ims.entity.params.ServerPatchIdParam;
import com.bocloud.ims.entity.resource.AlarmThreshold;
import com.bocloud.ims.entity.resource.CloudServer;
import com.bocloud.ims.entity.resource.Server;
import com.bocloud.ims.interfaces.resource.ServerService;
import com.bocloud.service.core.CurrentService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.*;

/**
 * 物理服务器相关接口 前端请求的时候加入type参数，取值为： HOST CloudProvider INSTALLATION
 *
 * @author dmw
 */
@RestController
@RequestMapping("/v1")
@Api(value = "物理服务器管理", tags = "物理服务器管理")
public class ServerController {
    private static Logger logger = LoggerFactory.getLogger(ServerController.class);
    private static final String SERVER_SERVICE = "ServerService";
    @Autowired
    private CurrentService currentService;
    @Autowired
    private ApplicationContext applicationContext;

    /**
     * 获取服务器列表
     *
     * @param pager
     * @return
     */
    @ApiOperation(tags = {"CMC", "CSC"}, value = "获取物理服务器列表", httpMethod = "GET")
    @GetMapping("/hosts")
    @Log(module = BoCloudService.IMS, target = "物理服务器", operation = "查看物理服务器列表")
    public BocloudResult<GridBean> list(Pager pager, @RequestParam(value = Common.TYPE, required = false) String type) {
        ServerService dispatchService = applicationContext
                .getBean(type == null ? SERVER_SERVICE : type.toLowerCase() + SERVER_SERVICE, ServerService.class);
        return dispatchService.list(pager);
    }

    /**
     * 根据condition获取物理服务器列表
     *
     * @param pager
     * @return
     */
    @ApiOperation(tags = {"CMC", "CSC"}, value = "根据condition获取物理服务器列表", httpMethod = "GET")
    @GetMapping("/hosts/condition")
    @Log(module = BoCloudService.IMS, target = "物理服务器", operation = "查看物理服务器列表")
    public BocloudResult condition(Pager pager, @RequestParam(value = Common.CONDITION, required = false) String condition,
                                   @RequestParam(value = Common.TYPE, required = false) String type, HttpServletRequest request,
                                   HttpServletResponse response) {
        ServerService dispatchService = applicationContext
                .getBean(type == null ? SERVER_SERVICE : type.toLowerCase() + SERVER_SERVICE, ServerService.class);
        if (StringUtils.isNotEmpty(condition)) {
            JSONObject conditionObj = JSONObject.parseObject(condition);
            if ("download".equals(conditionObj.getString("condition"))) {
                Map<String, Object> paramMap = pager.toMap();
                List<Param> params = JSONArray.parseArray(paramMap.get(Common.PARAMS).toString(), Param.class);
                return download(JSON.toJSONString(params.get(0).getParam()), request, response, dispatchService);
            }
            if ("queryByIp".equalsIgnoreCase(conditionObj.getString("condition"))) {
                return dispatchService.queryByIp(conditionObj.getString("ip"));
            }
            if ("listbycluster".equalsIgnoreCase(conditionObj.getString("condition"))) {
                return dispatchService.listByCluster(conditionObj.getLong("clusterId"));
            }
            if ("listByDefaultCluster".equalsIgnoreCase(conditionObj.getString("condition"))) {
                return dispatchService.listByDefaultCluster(conditionObj.getLong("vendorId"));
            }
            if ("listByCondition".equalsIgnoreCase(conditionObj.getString("condition"))) {
                return dispatchService.list(conditionObj.toJSONString());
            }
            if ("listByServerConfigs".equalsIgnoreCase(conditionObj.getString("condition"))) {
                return dispatchService.listByServerConfigs(conditionObj.getJSONArray("serverIds"));
            }
            if ("listByVendorType".equalsIgnoreCase(conditionObj.getString("condition"))) {
                return dispatchService.listByVendorType(conditionObj.toJSONString());
            }
        }
        return new BocloudResult(false, "查询失败");
    }

    /**
     * 添加物理主机
     *
     * @param params  物理主机属性信息的json字符串，在数据转换时会发生异常，对外抛出400异常【Bad Request】
     * @param context 操作者ID
     * @return 添加结果
     */
    @ApiOperation(tags = {"CMC", "CSC"}, value = "添加服务器", httpMethod = "POST")
    @PostMapping("/hosts")
    @Log(module = BoCloudService.IMS, target = "物理服务器", operation = "添加物理服务器")
    public BocloudResult create(@RequestBody ServerCreateParam params,
                                @RequestParam(value = Common.TYPE, required = false) String type,
                                @Value(Common.REQ_CONTEXT) RequestContext context) {
        type = StringUtils.isBlank(type) ? params.getType() : type;
        ServerService dispatchService = applicationContext
                .getBean(type == null ? SERVER_SERVICE : type.toLowerCase() + SERVER_SERVICE, ServerService.class);
        if ("HOST".equals(params.getType())) {
            // 保存资源纳管中的物理主机
            return dispatchService.create(params.getParams(), context, false, currentService.getInstance());
        } else {
            // 保存云平台中的物理机
            HostOperateModel model = JSONObject.parseObject(params.getParams(), HostOperateModel.class);
            return dispatchService.create(model, context);
        }
    }

    /**
     * 修改物理主机
     *
     * @param params 物理主机属性信息的json字符串，在数据转换时会发生异常，对外抛出400异常【Bad Request】
     * @param id     需要修改的物理主机ID
     * @return
     */
    @ApiOperation(tags = {"CMC", "CSC"}, value = "修改服务器", httpMethod = "PUT")
    @PutMapping("/hosts/{id}")
    @Log(module = BoCloudService.IMS, target = "物理服务器", operation = "修改物理服务器")
    public BocloudResult<String> modify(@RequestBody ServerCreateParam params, @PathVariable(value = Common.ID) Long id,
                                        @Value(Common.REQ_CONTEXT) RequestContext context) {
        ServerService dispatchService = applicationContext
                .getBean(params.getType() == null ? SERVER_SERVICE : params.getType().toLowerCase() + SERVER_SERVICE, ServerService.class);
        return dispatchService.modify(JSONObject.toJSONString(params), context);
    }

    /**
     * 根据uuid修改物理主机
     *
     * @param params  物理主机属性信息的json字符串
     * @param uuid    物理主机的uuid
     * @param context 用户
     * @return 操作结果
     * @author sxp
     * @since Mar 7, 2018
     */
    @ApiOperation(tags = {"CMC", "CSC"}, value = "修改物理服务器", httpMethod = "POST")
    @Log(module = BoCloudService.IMS, target = "物理服务器", operation = "修改物理服务器")
    @RequestMapping(value = "/server/{uuid}/uuid/modify", method = {RequestMethod.POST})
    public BocloudResult modifyByUuid(@RequestParam(value = Common.PARAMS, required = true) String params,
                                      @RequestParam(value = Common.TYPE, required = false) String type,
                                      @PathVariable(value = Common.UUID) String uuid, @Value(Common.REQ_CONTEXT) RequestContext context) {
        ServerService dispatchService = applicationContext
                .getBean(type == null ? SERVER_SERVICE : type.toLowerCase() + SERVER_SERVICE, ServerService.class);
        return dispatchService.modifyByUuid(params, uuid, context);
    }

    /**
     * 移除物理主机
     *
     * @param id      物理主机ID
     * @param context 操作者
     * @return
     */
    @ApiOperation(tags = {"CMC", "CSC"}, value = "移除物理服务器", httpMethod = "DELETE")
    @DeleteMapping("/hosts/{id}")
    @Log(module = BoCloudService.IMS, target = "物理服务器", operation = "移除物理服务器")
    public BocloudResult<String> remove(@PathVariable(value = Common.ID) Long id,
                                        @RequestParam(value = Common.PARAMS, required = false) String params,
                                        @RequestParam(value = Common.TYPE, required = false) String type,
                                        @Value(Common.REQ_CONTEXT) RequestContext context) {
        boolean force = Optional.ofNullable(params).map(JSON::parseObject)
                .map(o -> o.getBoolean("force")).orElse(false);
        // installation表示原来的物理装机，涉及到installation的地方将type置空，走ServerServiceImpl
        if ("installation".equalsIgnoreCase(type)) type = null;
        ServerService dispatchService = applicationContext
                .getBean(type == null ? SERVER_SERVICE : type.toLowerCase() + SERVER_SERVICE, ServerService.class);
        return dispatchService.remove(id, force, context);
    }

    /**
     * 查看物理主机详细信息
     *
     * @param id      物理主机ID
     * @param context 操作者
     * @return 操作结果
     */
    @ApiOperation(tags = {"CMC", "CSC"}, value = "查看物理主机详情", httpMethod = "GET")
    @GetMapping("/hosts/{id}")
    @Log(module = BoCloudService.IMS, target = "物理服务器", operation = "查看物理主机详情")
    public BocloudResult detail(@PathVariable(value = Common.ID) Long id,
                                @RequestParam(value = Common.TYPE, required = false) String type,
                                @Value(Common.REQ_CONTEXT) RequestContext context) {
        ServerService dispatchService = applicationContext
                .getBean(type == null ? SERVER_SERVICE : type.toLowerCase() + SERVER_SERVICE, ServerService.class);
        return dispatchService.detail(id);
    }

    /**
     * 查看物理主机基本信息
     *
     * @param id      物理主机ID
     * @param context 操作者
     * @return 操作结果
     */
    @ApiOperation(tags = {"CMC", "CSC"}, value = "查看物理主机基本信息", httpMethod = "GET")
    @Log(module = BoCloudService.IMS, target = "物理服务器", operation = "查看物理主机基本信息")
    @RequestMapping(value = "/hosts/{id}/basic", method = {RequestMethod.GET})
    public BocloudResult<Server> basic(@PathVariable(value = Common.ID) Long id,
                                       @RequestParam(value = Common.TYPE, required = false) String type,
                                       @Value(Common.REQ_CONTEXT) RequestContext context) {
        ServerService dispatchService = applicationContext
                .getBean(type == null ? SERVER_SERVICE : type.toLowerCase() + SERVER_SERVICE, ServerService.class);
        return dispatchService.basic(id);
    }

    /**
     * 设备更新
     *
     * @param id
     * @param context
     * @return
     */
    @ApiOperation(tags = {"CMC", "CSC"}, value = "操作物理主机", httpMethod = "PATCH")
    @Log(module = BoCloudService.IMS, target = "物理服务器", operation = "操作物理主机")
    @PatchMapping(value = "/hosts/{id}")
    public BocloudResult patch(@PathVariable(value = Common.ID) Long id,
                               @RequestBody ServerPatchIdParam params,
                               @RequestParam(value = Common.ACTION, required = false) String action,
                               @RequestParam(value = Common.TYPE, required = false) String type,
                               @Value(Common.REQ_CONTEXT) RequestContext context) {
        action = StringUtils.isBlank(action) ? params.getAction() : action;
        type = StringUtils.isBlank(type) ? params.getType() : type;
        ServerService dispatchService = applicationContext.getBean(type == null ? SERVER_SERVICE : type.toLowerCase() + SERVER_SERVICE, ServerService.class);
        if ("start".equals(action)) {
            return dispatchService.start(id, context);
        } else if ("stop".equals(action)) {
            return dispatchService.stop(id, context);
        } else if ("restart".equals(action)) {
            return dispatchService.restart(id, context);
        } else if ("isolate".equals(action)) {
            return dispatchService.isolate(id, context);
        } else if ("recover".equals(action)) {
            return dispatchService.recover(id, context);
        } else if ("reconnect".equals(action)) {
            return dispatchService.reconn(id, context);
        } else if ("disconnect".equals(action)) {
            return dispatchService.disconn(id, context);
        } else if ("entermaintain".equals(action)) {
            return dispatchService.entermaintain(id, context);
        } else if ("exitmaintain".equals(action)) {
            return dispatchService.exitmaintain(id, context);
        } else if ("updateRack".equals(action)) {
            return dispatchService.patch(id, params.getRackId(), context);
        } else if ("reboot".equals(action)) {
            return dispatchService.restart(id, context);
        }
        logger.warn("action {} not supported", action);
        return ResultTools.formatErrResult();
    }

    @ApiOperation(tags = {"CMC", "CSC"}, value = "物理主机移入机柜", httpMethod = "POST")
    @Log(module = BoCloudService.IMS, target = "物理服务器", operation = "物理主机移入机柜")
    @RequestMapping(value = "/server/{id}/inRack", method = {RequestMethod.POST})
    public BocloudResult inRack(@RequestParam(value = Common.RACK, required = true) Long rackId,
                                @PathVariable(value = Common.ID) Long id, @Value(Common.REQ_CONTEXT) RequestContext context) {
        return ResultTools.noImplementedResult();
    }

    /**
     * 物理机批量启动
     *
     * @param params
     * @param context
     * @return
     */
    @ApiOperation(tags = {"CMC", "CSC"}, value = "批量操作物理主机", httpMethod = "PATCH")
    @Log(module = BoCloudService.IMS, target = "物理服务器", operation = "批量操作物理主机")
    @PatchMapping("/hosts")
    public BocloudResult batchPatch(@RequestParam(value = Common.ACTION, required = false) String action,
                                    @RequestBody String params,
                                    @RequestParam(value = Common.TYPE, required = false) String type,
                                    @Value(Common.REQ_CONTEXT) RequestContext context) {
        if (StringUtils.isBlank(action)) {
            JSONObject object = JSONTools.isJSONObj(params);
            if (null != object) {
                action = StringUtils.isBlank(action) ? object.getString(Common.ACTION) : action;
                type = StringUtils.isBlank(type) ? object.getString(Common.TYPE) : type;
            }
        }
        ServerService dispatchService = applicationContext.getBean(type == null ? SERVER_SERVICE : type.toLowerCase() + SERVER_SERVICE, ServerService.class);
        if ("start".equals(action)) {
            return dispatchService.batchStart(params, context);
        } else if ("stop".equals(action)) {
            return dispatchService.batchStop(params, context);
        }
        logger.warn("action {} not supported", action);
        return ResultTools.formatErrResult();
    }

    /**
     * 物理机批量删除
     *
     * @param params
     * @param context
     * @return
     */
    @ApiOperation(tags = {"CMC", "CSC"}, value = "批量删除物理主机", httpMethod = "DELETE")
    @DeleteMapping("/hosts")
    @Log(module = BoCloudService.IMS, target = "物理服务器", operation = "批量删除物理主机")
    public BocloudResult batchRemove(@RequestParam(value = Common.PARAMS, required = true) String params,
                                     @RequestParam(value = Common.TYPE, required = false) String type,
                                     @Value(Common.REQ_CONTEXT) RequestContext context) {
        ServerService dispatchService = applicationContext
                .getBean(type == null ? SERVER_SERVICE : type.toLowerCase() + SERVER_SERVICE, ServerService.class);
        return dispatchService.batchRemove(params, context);
    }

    /**
     * 物理机上创建标准交换机
     *
     * @param params
     * @param context
     * @return
     */
    @ApiOperation(tags = {"CMC", "CSC"}, value = "物理主机上创建标准交换机", httpMethod = "POST")
    @Log(module = BoCloudService.IMS, target = "物理服务器", operation = "物理主机上创建标准交换机")
    @RequestMapping(value = "/hosts/switches", method = {RequestMethod.POST})
    public BocloudResult createVSwitch(@RequestBody SwitchModel model,
                                       @Value(Common.REQ_CONTEXT) RequestContext context) {
        if (null != model) {
        	String type = model.getType();
            ServerService dispatchService = applicationContext
                    .getBean(type == null ? SERVER_SERVICE : type.toLowerCase() + SERVER_SERVICE, ServerService.class);
            return dispatchService.createVSwitch(model, context);
        } else {
            return ResultTools.formatErrResult();
        }
    }

    /**
     * 获取监控数据接口
     *
     * @param params
     * @param context
     * @return
     */
    @ApiOperation(tags = {"CMC", "CSC"}, value = "获取监控数据", httpMethod = "GET")
    @Log(module = BoCloudService.IMS, target = "物理服务器", operation = "获取监控数据")
    @RequestMapping(value = "/hosts/{id}/metrics", method = {RequestMethod.GET})
    public BocloudResult performance(@RequestParam(value = Common.PARAMS, required = false) String params,
                                     @RequestParam(value = Common.TYPE, required = false) String type,
                                     @Value(Common.REQ_CONTEXT) RequestContext context, @PathVariable(value = Common.ID) Long id) {
        ServerService dispatchService = applicationContext.getBean(type == null ? SERVER_SERVICE : (type.toLowerCase() + SERVER_SERVICE), ServerService.class);
        return dispatchService.performance(params, id, context);
    }

    /**
     * 移动
     *
     * @param params
     * @param context
     * @return
     */
    @ApiOperation(tags = {"CMC", "CSC"}, value = "移动物理主机", httpMethod = "PUT")
    @Log(module = BoCloudService.IMS, target = "物理服务器", operation = "移动物理主机")
    @RequestMapping(value = "/clusters/{id}/hosts", method = {RequestMethod.PUT})
    public BocloudResult move(@RequestParam(value = Common.PARAMS, required = false) String params,
                              @RequestParam(value = Common.TYPE, required = false) String type,
                              @Value(Common.REQ_CONTEXT) RequestContext context, @PathVariable(value = Common.ID) Long id) {
        JSONObject object = JSONTools.isJSONObj(params);
        if (null != object) {
            HostOperateModel model = JSONObject.parseObject(object.toJSONString(), HostOperateModel.class);
            ServerService dispatchService = applicationContext
                    .getBean(type == null ? SERVER_SERVICE : type.toLowerCase() + SERVER_SERVICE, ServerService.class);
            return dispatchService.move(model, context);
        }
        return ResultTools.formatErrResult();
    }

    /**
     * 更新物理机的资源分组
     *
     * @param params
     * @param context
     * @return
     */
    @ApiOperation(tags = {"CMC", "CSC"}, value = "更新资源分组", httpMethod = "PUT")
    @Log(module = BoCloudService.IMS, target = "物理服务器", operation = "更新资源分组")
    @RequestMapping(value = "/hosts/groups", method = {RequestMethod.PUT})
    public BocloudResult<String> updateResourceGroup(@RequestParam(value = Common.PARAMS, required = false) String params,
                                                     @RequestParam(value = Common.TYPE, required = false) String type,
                                                     @Value(Common.REQ_CONTEXT) RequestContext context, @PathVariable(value = Common.ID) Long id) {
        JSONObject object = JSONTools.isJSONObj(params);
        if (null != object) {
            String idStr = object.getString("id");
            String resourceGroup = object.getString("resourceGroup");
            if (StringUtils.isNotEmpty(idStr)) {
                String[] ids = idStr.split(",");
                ServerService dispatchService = applicationContext
                        .getBean(type == null ? SERVER_SERVICE : type.toLowerCase() + SERVER_SERVICE, ServerService.class);
                return dispatchService.updateResourceGroup(ids, resourceGroup, context.getTarget());
            }
        }
        return ResultTools.formatErrResult();
    }

    /**
     * 查询指定集群下的宿主机
     *
     * @param listByCluster
     * @param context
     * @return
     */
    @ApiOperation(tags = {"CMC", "CSC"}, value = "查询指定集群下的宿主机", httpMethod = "GET")
    @Log(module = BoCloudService.IMS, target = "物理服务器", operation = "查询指定集群下的宿主机")
    @RequestMapping(value = "/clusters/{id}/hosts", method = {RequestMethod.GET})
    public BocloudResult<List<Server>> listByCluster(@PathVariable(value = Common.ID) Long listByCluster,
                                                     @RequestParam(value = Common.TYPE, required = false) String type,
                                                     @Value(Common.REQ_CONTEXT) RequestContext context) {
        ServerService dispatchService = applicationContext
                .getBean(type == null ? SERVER_SERVICE : type.toLowerCase() + SERVER_SERVICE, ServerService.class);
        return dispatchService.listByCluster(listByCluster);
    }

    /**
     * 查询云平台下的宿主机
     *
     * @param params
     * @return
     */
    @ApiOperation(tags = {"CMC", "CSC"}, value = "查询云平台下的宿主机", httpMethod = "GET")
    @Log(module = BoCloudService.IMS, target = "物理服务器", operation = "查询云平台下的宿主机")
    @RequestMapping(value = "/vendors/{id}/hosts", method = {RequestMethod.GET})
    public BocloudResult<List<Server>> listByVendor(@RequestParam(value = Common.PARAMS, required = false) String params,
                                                    @RequestParam(value = Common.TYPE, required = false) String type,
                                                    @PathVariable(value = Common.ID) Long id) {
        JSONObject object = JSONTools.isJSONObj(params);
        if (null != object) {
            ServerService dispatchService = applicationContext
                    .getBean(type == null ? SERVER_SERVICE : type.toLowerCase() + SERVER_SERVICE, ServerService.class);
            return dispatchService.listByVendor(id);
        }
        return ResultTools.formatErrResult();
    }

    /**
     * 更新物理主机状态
     *
     * @param params
     * @param uuid
     * @return
     */
    @ApiOperation(tags = {"CMC", "CSC"}, value = "更新物理主机状态", httpMethod = "POST")
    @Log(module = BoCloudService.IMS, target = "物理服务器", operation = "更新物理主机状态")
    @RequestMapping(value = "/server/{uuid}/uuid/status/update", method = {RequestMethod.POST})
    public BocloudResult updateStatus(@RequestParam(value = Common.PARAMS, required = true) String params,
                                      @RequestParam(value = Common.TYPE, required = false) String type,
                                      @PathVariable(value = Common.UUID) String uuid) {
        ServerService dispatchService = applicationContext
                .getBean(type == null ? SERVER_SERVICE : type.toLowerCase() + SERVER_SERVICE, ServerService.class);
        return dispatchService.updateStatus(params, uuid);
    }

    /**
     * 设置主机告警阈值
     *
     * @param params
     * @return
     */
	@ApiOperation(tags = { "CMC", "CSC" }, value = "设置主机告警阈值", httpMethod = "POST")
	@Log(module = BoCloudService.IMS, target = "物理服务器", operation = "设置主机告警阈值")
	@PostMapping("/hosts/{id}/thresholds")
	public BocloudResult<String> createAlarm(@PathVariable(value = Common.ID) Long id,
			@RequestBody AlarmThreshold alarmThreshold) {
		if (null != alarmThreshold) {
			String type = alarmThreshold.getType();
			ServerService dispatchService = applicationContext
					.getBean(type == null ? SERVER_SERVICE : type.toLowerCase() + SERVER_SERVICE, ServerService.class);
			return dispatchService.createAlarm(alarmThreshold);
		}
		return ResultTools.formatErrResult();
	}

    /**
     * 查询告警阈值详情
     *
     * @param id
     * @return
     */
    @ApiOperation(tags = {"CMC", "CSC"}, value = "查询告警阈值详情", httpMethod = "GET")
    @Log(module = BoCloudService.IMS, target = "物理服务器", operation = "查询告警阈值详情")
    @GetMapping("/hosts/{id}/thresholds")
    public BocloudResult<AlarmThreshold> getAlarm(@PathVariable(value = Common.ID) Long id,
                                                  @RequestParam(value = Common.TYPE, required = false) String type) {
        ServerService dispatchService = applicationContext
                .getBean(type == null ? SERVER_SERVICE : type.toLowerCase() + SERVER_SERVICE, ServerService.class);
        return dispatchService.getAlarm(id);
    }

    /**
     * 下载excel模板
     *
     * @param params
     * @return
     */
    @ApiOperation(tags = {"CMC", "CSC"}, value = "下载导入文件模板", httpMethod = "GET")
    @Log(module = BoCloudService.IMS, target = "物理服务器", operation = "下载导入文件模板")
    @RequestMapping(value = "/hosts/download", method = {RequestMethod.GET})
    public BocloudResult<Map<String, Object>> download(@RequestParam(value = Common.PARAMS, required = true) String params,
                                                       @RequestParam(value = Common.TYPE, required = false) String type,
                                                       HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> paramsMap = new HashMap<>();
        JSONValidator jsonValidator = JSONValidator.from(params);
        if (jsonValidator.validate() && jsonValidator.getType().equals(JSONValidator.Type.Object)) {
            paramsMap = JSONObject.parseObject(params, HashMap.class);
        } else if (jsonValidator.validate() && jsonValidator.getType().equals(JSONValidator.Type.Array)) {
            paramsMap = JSONObject.parseArray(params).getJSONObject(0).getJSONObject("param");
        }
        ServerService dispatchService = applicationContext
                .getBean(type == null ? SERVER_SERVICE : type.toLowerCase() + SERVER_SERVICE, ServerService.class);
        return download(JSON.toJSONString(paramsMap), request, response, dispatchService);
    }

    /**
     * todo 需要跟前段重新商量接口参数
     *
     * @param params
     * @param request
     * @param response
     * @return
     */
    public BocloudResult<Map<String, Object>> download(String params, HttpServletRequest request, HttpServletResponse response,
                                                       ServerService serverService) {
        Map<String, Object> paramsMap = JSONObject.parseObject(params, HashMap.class);
        BocloudResult<Map<String, Object>> bocloudResult = serverService.download(paramsMap);
        if (bocloudResult.isSuccess()) {
            String content = null;
            try {
                @SuppressWarnings("unchecked")
                Map<String, Object> result = JSONObject.parseObject(JSONObject.toJSONString(bocloudResult.getData()),
                        HashMap.class);
                //response.setContentType("application/vnd.ms-excel"); // 避免一个warning
                String fileName = result.get("fileName").toString();
                final String userAgent = request.getHeader("user-agent").toLowerCase();
                if (userAgent.contains("trident") || userAgent.contains("edge")) {
                    fileName = URLEncoder.encode(fileName, "UTF-8");
                } else {
                    fileName = new String(fileName.getBytes("utf-8"), "iso-8859-1");
                }
                response.setCharacterEncoding("utf-8");
                response.setHeader("Content-Disposition", "attachment;fileName=" + fileName);
                OutputStream outputStream = response.getOutputStream();
                content = (String) result.get("data");

                if (content != null) {
                    byte[] bytes = Base64.getDecoder().decode(content);
                    outputStream.write(bytes);
                    outputStream.close();
                }
            } catch (Exception e) {
                return new BocloudResult(false, "内部错误");
            }
        }
        return bocloudResult;
    }

    /**
     * 上传批量新增
     *
     * @param request
     * @param response
     * @param context
     * @return
     * @throws IOException
     */
    @ApiOperation(tags = {"CMC", "CSC"}, value = "上传", httpMethod = "POST")
    @Log(module = BoCloudService.IMS, target = "物理服务器", operation = "上传")
    @RequestMapping(value = "/hosts/upload", method = {RequestMethod.POST})
    public BocloudResult upload(HttpServletRequest request, HttpServletResponse response,
                                @RequestParam(value = Common.TYPE, required = false) String type,
                                @Value(Common.REQ_CONTEXT) RequestContext context) throws IOException {
        try {
            MultipartHttpServletRequest multipartHttpServletRequest = (MultipartHttpServletRequest) request;
            MultiValueMap<String, MultipartFile> multiFileMap = multipartHttpServletRequest.getMultiFileMap();
            MultipartFile item = null;
            if (multiFileMap.values().size() > 0) {
                List<MultipartFile> multiFileList = multiFileMap.values().iterator().next();
                item = multiFileList.get(0);
            }
            ServerService dispatchService = applicationContext
                    .getBean(type == null ? SERVER_SERVICE : type.toLowerCase() + SERVER_SERVICE, ServerService.class);
            return dispatchService.upload(null, item, context.getTarget(), currentService.getInstance());
        } catch (Exception e) {
            logger.info("上传失败", e);
        }
        return new BocloudResult(false, "文件错误");
    }

    /**
     * 批量配置宿主机标签
     *
     * @param param
     * @param type
     * @param context
     * @return
     */
    @ApiOperation(tags = {"CMC", "CSC"}, value = "批量配置宿主机标签", httpMethod = "PUT")
    @Log(module = BoCloudService.IMS, target = "宿主机", operation = "批量配置宿主机标签")
    @PutMapping("/hosts/tags")
    public BocloudResult<String> batchModifyLabel(@RequestBody(required = false) LabelParam param,
                                                  @RequestParam(value = Common.TYPE, required = false) String type,
                                                  @Value(Common.REQ_CONTEXT) RequestContext context) {
        String params = null;
        if (null != param) {
            params = JSONObject.toJSONString(param);
        }
        ServerService dispatchService = applicationContext
                .getBean(type == null ? SERVER_SERVICE : type.toLowerCase() + SERVER_SERVICE, ServerService.class);
        return dispatchService.batchModifyLabel(params, context);
    }


    /**
     * 查看未管理的powervc云主机
     *
     * @param pager
     * @param context
     * @return
     */
    @ApiOperation(tags = {"CMC", "CSC"}, value = "查看未管理的powervc云主机", httpMethod = "GET")
    @Log(module = BoCloudService.IMS, target = "物理服务器", operation = "查看未管理的powervc云主机")
    @RequestMapping(value = "/hosts/{id}/vms", method = {RequestMethod.GET})
    public BocloudResult<List<CloudServer>> listUnmanagedPowervm(@PathVariable(value = Common.ID) Long id, Pager pager,
                                                                 @RequestParam(value = Common.CONDITION, required = false) String condition,
                                                                 @Value(Common.REQ_CONTEXT) RequestContext context) {
        ServerService dispatchService = applicationContext
                .getBean(CloudProvider.POWERVC.name().toLowerCase() + SERVER_SERVICE, ServerService.class);
        if (StringUtils.isNotEmpty(condition)) {
            JSONObject conditionObj = JSONObject.parseObject(condition);
            if ("listUnmanagedPowervm".equalsIgnoreCase(conditionObj.getString("condition"))) {
                return dispatchService.listUnmanagedPowervm(pager.getPage(), pager.getRows(), pager.getParams(),
                        pager.getSorter(), pager.getSimple());
            }
            if ("listvmByvhost".equalsIgnoreCase(conditionObj.getString("condition"))) {
                Long venderId = conditionObj.getJSONObject("param").getLong(Common.VENDORID);
                String hostname = conditionObj.getJSONObject("param").getString("hostname");
                return dispatchService.listvmByvhost(venderId, hostname);
            }
        }
        return new BocloudResult(false, "未知类型");
    }

    /**
     * powervc添加未管理的云主机
     *
     * @param params
     * @param context
     * @return
     */
    @ApiOperation(tags = {"CMC", "CSC"}, value = "powervc添加未管理云主机", httpMethod = "POST")
    @Log(module = BoCloudService.IMS, target = "物理服务器", operation = "powervc添加未管理云主机")
    @RequestMapping(value = "/hosts/{id}/vms", method = {RequestMethod.POST})
    public BocloudResult onboardPowervm(@RequestParam(value = Common.PARAMS, required = false) String params,
                                        @PathVariable(value = Common.ID) Long id, @Value(Common.REQ_CONTEXT) RequestContext context) {
        JSONObject jsonObject = JSONTools.isJSONObj(params);
        if (null != jsonObject) {
            ServerService dispatchService = applicationContext
                    .getBean(CloudProvider.POWERVC.name().toLowerCase() + SERVER_SERVICE, ServerService.class);
            return dispatchService.onboardPowervm(params, context);
        }
        return ResultTools.formatErrResult();
    }

    /**
     * powervc取消管理物理机上的云主机
     *
     * @param params
     * @param context
     * @return
     */
    @ApiOperation(tags = {"CMC", "CSC"}, value = "powervc取消管理云主机", httpMethod = "DELETE")
    @Log(module = BoCloudService.IMS, target = "物理服务器", operation = "powervc取消管理云主机")
    @RequestMapping(value = "/hosts/{id}/vms", method = {RequestMethod.DELETE})
    public BocloudResult unmanagePowervm(@RequestParam(value = Common.PARAMS, required = false) String params,
                                         @PathVariable(value = Common.ID) Long id, @Value(Common.REQ_CONTEXT) RequestContext context) {
        JSONObject jsonObject = JSONTools.isJSONObj(params);
        if (null != jsonObject) {
            return applicationContext
                    .getBean(CloudProvider.POWERVC.name().toLowerCase() + SERVER_SERVICE, ServerService.class)
                    .unmanagePowervm(params, context);
        }
        return ResultTools.formatErrResult();
    }

    /**
     * 查询hmc下的宿主机
     *
     * @return
     */
    @ApiOperation(tags = {"CMC", "CSC"}, value = "查询云平台下的宿主机", httpMethod = "GET")
    @Log(module = BoCloudService.IMS, target = "物理服务器", operation = "查询云平台下的宿主机")
    @RequestMapping(value = "/hmcs/{id}/hosts", method = {RequestMethod.GET})
    public BocloudResult listByHmc(@PathVariable(value = Common.ID) Long id) {
        return applicationContext.getBean(CloudProvider.HMC.name().toLowerCase() + SERVER_SERVICE, ServerService.class)
                .listByHmc(id);
    }

    @ApiOperation(value = "同步宿主机下云主机", httpMethod = "POST")
    @Log(module = BoCloudService.IMS, target = "云平台", operation = "同步宿主机下云主机")
    @PostMapping("/hosts/{id}/sync")
    public BocloudResult sync(@PathVariable(value = Common.ID) Long id,
                              @Value(Common.REQ_CONTEXT) RequestContext context) {
        return applicationContext.getBean(CloudProvider.VMWARE.name().toLowerCase() + SERVER_SERVICE, ServerService.class).syncVmByHost(id, context);
    }

    @ApiOperation(tags = {"CMC", "CSC"}, value = "网口列表", httpMethod = "GET")
    @GetMapping("/ifaces")
    @Log(module = BoCloudService.IMS, target = "物理服务器", operation = "网口列表")
    public BocloudResult<List<SangforIfacesModel>> ifaces(Pager pager,@RequestParam(value = Common.TYPE, required = false) String type,
        @RequestParam(required = true) String ifaces, @RequestParam(required = true) Long vendorId) {
        ServerService dispatchService = applicationContext.getBean(type == null ? SERVER_SERVICE : type.toLowerCase() + SERVER_SERVICE, ServerService.class);
        return dispatchService.ifaces(pager,ifaces,vendorId);
    }

    @ApiOperation(tags = {"CMC", "CSC"}, value = "网口列表", httpMethod = "GET")
    @GetMapping("/ifaces/list")
    @Log(module = BoCloudService.IMS, target = "物理服务器", operation = "物理网络")
    public BocloudResult ifaces(Pager pager, @RequestParam(value = Common.TYPE, required = false) String type) {
        ServerService dispatchService = applicationContext.getBean(type == null ? SERVER_SERVICE : type.toLowerCase() + SERVER_SERVICE, ServerService.class);
        return dispatchService.ifaces(pager);
    }
}
