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

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.model.BatchUpdateImageParam;
import com.bocloud.cmp.model.ImgBean;
import com.bocloud.common.annotations.Log;
import com.bocloud.common.enums.BoCloudService;
import com.bocloud.common.model.BocloudResult;
import com.bocloud.common.model.GridBean;
import com.bocloud.common.model.Pager;
import com.bocloud.common.model.RequestContext;
import com.bocloud.common.utils.Common;
import com.bocloud.common.utils.JSONTools;
import com.bocloud.common.utils.ResultTools;
import com.bocloud.ims.entity.resource.CloudServer;
import com.bocloud.ims.entity.resource.Image;
import com.bocloud.ims.entity.resource.Volume;
import com.bocloud.ims.interfaces.resource.ImageService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.io.IOUtils;
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.web.bind.annotation.*;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.List;

@RestController
@RequestMapping("/v1/images")
@Api(value = "镜像管理", tags = "镜像管理")
public class ImageController {

    private static final Logger logger = LoggerFactory.getLogger(ImageController.class);
    @Autowired
    private ImageService imageService;
    private static final String IMAGE_SERVICE = "imageService";
    @Autowired
    private ApplicationContext applicationContext;

    /**
     * 添加
     *
     * @param bean
     * @param type
     * @param context
     * @return
     */
    @ApiOperation(tags = {"CMC", "CSC"}, value = "创建镜像", httpMethod = "POST")
    @PostMapping
    @Log(module = BoCloudService.IMS, target = "镜像", operation = "创建镜像")
    public BocloudResult create(@RequestBody Image bean,
                                @RequestParam(value = Common.TYPE, required = false) String type,
                                @Value(Common.REQ_CONTEXT) RequestContext context) {
        type = StringUtils.isBlank(type) ? bean.getType() : type;
        ImageService dispatchService = applicationContext
                .getBean((type == null ? "" : type.toLowerCase()) + IMAGE_SERVICE, ImageService.class);
        return dispatchService.create(bean, context);
    }

    /**
     * 查看镜像列表
     *
     * @param pager
     * @param context
     * @return
     */
    @ApiOperation(tags = {"CMC", "CSC"}, value = "查询镜像列表", httpMethod = "GET")
    @GetMapping
    @Log(module = BoCloudService.IMS, target = "镜像", operation = "查看镜像列表")
    public BocloudResult list(Pager pager, @Value(Common.REQ_CONTEXT) RequestContext context) {
        return imageService.list(pager, context);
    }

    /**
     * 查看镜像列表
     *
     * @param condition
     * @param context
     * @return
     */
    @ApiOperation(tags = {"CMC", "CSC"}, value = "通过condition方式查询镜像列表", httpMethod = "GET")
    @GetMapping("/condition")
    @Log(module = BoCloudService.IMS, target = "镜像", operation = "查看镜像列表")
    public BocloudResult condition(@RequestParam(value = Common.CONDITION, required = false) String condition,
                                   @Value(Common.REQ_CONTEXT) RequestContext context) {
        return imageService.condition(condition, context);
    }

    /**
     * 获取当前nfs路径下所有的iso文件
     *
     * @return
     */
    @GetMapping(value = "/iso")
    @Log(module = BoCloudService.IMS, target = "镜像", operation = "查找nfs上的镜像")
    @ApiOperation(tags = {"CMC", "CSC"}, value = "查找nfs上的镜像", httpMethod = "GET")
    public BocloudResult isoList(@RequestParam(value = Common.TYPE, required = false) String type) {
        ImageService dispatchService = applicationContext
                .getBean((type == null ? "" : type.toLowerCase()) + IMAGE_SERVICE, ImageService.class);
        return dispatchService.isoList();
    }

    /**
     * 查看镜像详情
     *
     * @param id
     * @return
     */
    @ApiOperation(tags = {"CMC", "CSC"}, value = "查看镜像详情", httpMethod = "GET")
    @GetMapping("/{id}")
    @Log(module = BoCloudService.IMS, target = "镜像", operation = "查看镜像详情")
    public BocloudResult<Image> detail(@PathVariable(value = Common.ID) Long id) {
        return imageService.detail(id);
    }

    /**
     * 删除
     *
     * @param id
     * @param context
     * @return
     */
    @ApiOperation(tags = {"CMC", "CSC"}, value = "删除信息", httpMethod = "DELETE")
    @DeleteMapping("/{id}")
    @Log(module = BoCloudService.IMS, target = "镜像", operation = "删除镜像")
    public BocloudResult remove(@PathVariable(value = Common.ID) Long id,
                                @RequestParam(value = Common.TYPE, required = false) String type,
                                @Value(Common.REQ_CONTEXT) RequestContext context) {
        ImageService dispatchService = applicationContext
                .getBean((type == null ? "" : type.toLowerCase()) + IMAGE_SERVICE, ImageService.class);
        return dispatchService.remove(id, context);
    }

    /**
     * 修改镜像
     *
     * @param id
     * @param bean
     * @param context
     * @return
     */
    @ApiOperation(tags = {"CMC", "CSC"}, value = "修改镜像信息", httpMethod = "PUT")
    @PutMapping("/{id}")
    @Log(module = BoCloudService.IMS, target = "镜像", operation = "修改镜像")
    public BocloudResult modify(@PathVariable(value = Common.ID) Long id,
                                @RequestBody ImgBean bean, @Value(Common.REQ_CONTEXT) RequestContext context) {
        bean.setId(id);
        return imageService.modify(bean, context.getTarget());
    }

    /**
     * 更新镜像
     *
     * @param params
     * @param id
     * @param context
     * @return
     */
	@ApiOperation(tags = { "CMC", "CSC" }, value = "更新镜像信息", httpMethod = "PATCH")
	@PatchMapping("/{id}")
	@Log(module = BoCloudService.IMS, target = "镜像", operation = "更新镜像")
	public BocloudResult patch(@PathVariable(value = Common.ID) Long id, @RequestBody ImgBean imgBean,
			@Value(Common.REQ_CONTEXT) RequestContext context) {
		if (null == imgBean) {
			return new BocloudResult<>(false, "参数格式错误");
		}
		String type = imgBean.getType();
		ImageService dispatchService = applicationContext
				.getBean((type == null ? "" : type.toLowerCase()) + IMAGE_SERVICE, ImageService.class);
		JSONObject object = JSONTools.isJSONObj(JSON.toJSONString(imgBean));
		if (null != object) {
			return dispatchService.patch(id, object, context, imgBean.getAction());
		} else {
			return ResultTools.formatErrResult();
		}
	}

	/**
	 * 批量删除镜像
	 *
	 * @param params
	 * @param context
	 * @return
	 */
	@ApiOperation(tags = { "CMC", "CSC" }, value = "镜像批量删除", httpMethod = "DELETE")
	@Log(module = BoCloudService.IMS, target = "镜像", operation = "批量删除镜像")
	@DeleteMapping
	public BocloudResult batchRemove(@RequestBody List<Long> ids, @Value(Common.REQ_CONTEXT) RequestContext context) {
		return imageService.batchRemove(ids, context);
	}

    /**
     * 批量更新镜像
     *
     * @param params
     * @param context
     * @return
     */
    @ApiOperation(tags = {"CMC", "CSC"}, value = "批量更新镜像信息", httpMethod = "PUT")
    @Log(module = BoCloudService.IMS, target = "镜像", operation = "批量更新镜像")
    @PutMapping
    public BocloudResult batchUpdate(@RequestBody BatchUpdateImageParam params,
                                     @Value(Common.REQ_CONTEXT) RequestContext context) {
        return imageService.batchUpdate(params, context);
    }

    /**
     * 下载镜像
     *
     * @param id
     * @param request
     * @param response
     */
    @ApiOperation(tags = {"CMC", "CSC"}, value = "下载镜像", httpMethod = "GET")
    @GetMapping("/{id}/files")
    @Log(module = BoCloudService.IMS, target = "镜像", operation = "下载镜像")
    public void download(@PathVariable(value = Common.ID) Long id, HttpServletRequest request,
                         HttpServletResponse response) {
        BocloudResult result = imageService.download(id);
        if (result.isSuccess()) {
            InputStream fin = null;
            ServletOutputStream out = null;
            File file = null;
            try {
                logger.info("镜像文件路径：" + result.getData());
                file = new File((String) result.getData());
                if (!file.exists()) {
                    response.setCharacterEncoding("UTF-8");
                    response.getWriter().println(JSONObject.toJSON(result));
                    response.flushBuffer();
                    return;
                }
                fin = new FileInputStream(file);
                out = response.getOutputStream();
                response.setCharacterEncoding("utf-8");
                String fileName = file.getName();
                response.setContentType("application/octet-stream");
                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.setHeader("Content-Disposition", "attachment; fileName=" + fileName);
                IOUtils.copy(fin, out);
            } catch (Exception e) {
                logger.error("Get error message：", e);
                response.setCharacterEncoding("UTF-8");
                try {
                    response.getWriter().println(JSONObject.toJSON(result));
                    response.flushBuffer();
                } catch (IOException e1) {
                    logger.error("Get error message:{}", e1.getMessage());
                }
            } finally {
                try {
                    if (fin != null) {
                        fin.close();
                    }
                    if (out != null) {
                        out.close();
                    }
                    if (file != null) {
                        boolean flag = file.delete();
                        logger.info("临时镜像文件删除状态：{}", flag);
                    }
                } catch (IOException e) {
                    logger.error("Get error message:{}", e.getMessage());
                }

            }
        }
    }

    /**
     * 查询镜像使用的存储卷
     *
     * @param id
     * @return
     */
    @ApiOperation(tags = {"CMC", "CSC"}, value = "查询镜像使用的存储卷", httpMethod = "GET")
    @Log(module = BoCloudService.IMS, target = "映像和卷映射", operation = "查询镜像使用的存储卷")
    @GetMapping("/{id}/volumes")
    public BocloudResult<List<Volume>> listVolumeByImage(@PathVariable(value = Common.ID) Long id) {
        return imageService.listVolumeByImage(id);
    }

    /**
     * 查询镜像使用的云主机
     *
     * @param id
     * @return
     */
    @ApiOperation(tags = {"CMC", "CSC"}, value = "查询使用该镜像的云主机", httpMethod = "GET")
    @Log(module = BoCloudService.IMS, target = "镜像", operation = "查询使用该镜像的云主机")
    @GetMapping("/{id}/servers")
    public BocloudResult<GridBean<CloudServer>> listServersByImage(Pager pager, @PathVariable(value = Common.ID) Long id) {
        return imageService.listServerByImage(id, pager);
    }

    @ApiOperation(tags = {"CMC", "CSC"}, value = "复制镜像", httpMethod = "POST")
    @Log(module = BoCloudService.IMS, target = "镜像", operation = "复制镜像")
    @PostMapping("/copy")
    public BocloudResult copy(@RequestBody Image bean,
                              @Value(Common.REQ_CONTEXT) RequestContext context) {
        return imageService.copy(bean, context);
    }
}
