package cn.edu.zjvtit.cloudstorage.apiservice.controller;

import cn.edu.zjvtit.cloudstorage.apiservice.ApiServiceApplication;
import cn.edu.zjvtit.cloudstorage.apiservice.rabbitmq.topic.Sender;
import cn.edu.zjvtit.cloudstorage.apiservice.store.DataServerStore;
import com.rabbitmq.client.Channel;
import org.slf4j.Logger;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import cn.edu.zjvtit.cloudstorage.apiservice.result.Result;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.util.Map;
import java.util.logging.Level;

@RestController
public class ObjectsController {
    @Autowired
    private DataServerStore dataServerStore;
    @Autowired
    private Sender sender;

    @Autowired
    private Logger logger;
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @PutMapping("/objects/{filename}")
    public String putObject(@RequestBody byte[] requestBody, @RequestHeader Map<String, String> headers, @PathVariable("filename") String filename) throws IOException {
        String server = this.dataServerStore.selectRandomServer();
        logger.info("put object to server: " + server);
        if (server == null) {
            return new Result("no server available", "10000").toString();
        }
        String url = "http://" + server + "/objects/" + filename;
        // 发送post请求
        HttpEntity<byte[]> request = new HttpEntity<>(requestBody);
        this.restTemplate.exchange(url, HttpMethod.PUT, request, String.class);
        return (new Result("success", "10000")).toString();
    }


    @GetMapping("/objects/{filename}")
    public String getObject(HttpServletResponse response, @PathVariable("filename") String filename) throws IOException {
        // 查询哪台服务器有这个文件
        // 读取文件
        String queueName = filename;
        Channel channel = rabbitTemplate.getConnectionFactory().createConnection().createChannel(false);
        channel.queueDeclare(queueName, false, false, false, null);
        channel.queueBind(queueName, "exchange", "");
        sender.send(queueName);
        try {
            Object msg = rabbitTemplate.receiveAndConvert(queueName, 200);
            assert msg != null;
            logger.info(msg.toString());
            String url = "http://" + msg + "/objects/" + filename;

            ResponseEntity<String> res = this.restTemplate.getForEntity(url,String.class);
            response.reset();
            response.setContentType("application/octet-stream");
            response.setCharacterEncoding("utf-8");
            response.setContentLength((int) res.getHeaders().getContentLength());
            response.setHeader("Content-Disposition", "attachment;filename=" + filename );
            OutputStream os = response.getOutputStream();
            os.write(res.getBody().getBytes());
            os.close();
            return "";
        } catch (Exception e) {
            logger.info("locate object error", e);
            return new Result("file not exists", "10000").toString();
        }
    }

    @GetMapping("/locate/{filename}")
    public String locateObject(@PathVariable("filename") String filename) throws IOException {
        // 查询哪台服务器有这个文件
        String queueName = filename;
        Channel channel = rabbitTemplate.getConnectionFactory().createConnection().createChannel(false);
        channel.queueDeclare(queueName, false, false, false, null);
        channel.queueBind(queueName, "exchange", "");
        sender.send(queueName);
        try {
            Object msg = rabbitTemplate.receiveAndConvert(queueName, 200);
            assert msg != null;
            logger.info(msg.toString());
            return new Result("file in server:" + msg.toString(), "10000").toString();
        } catch (Exception e) {
            logger.info("locate object error", e);
            return new Result("file not exists", "10000").toString();
        }

    }


}
