package cokr.xit.fims.base.web;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringWriter;
import java.net.URISyntaxException;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.function.Consumer;
import java.util.regex.Matcher;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.apache.commons.io.FilenameUtils;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import cokr.xit.base.file.dao.FileMapper;
import cokr.xit.base.file.service.FileQuery;
import cokr.xit.base.file.service.bean.FileBean;
import cokr.xit.foundation.Downloadable;
import cokr.xit.foundation.data.DataObject;

@Controller
public class FileController extends cokr.xit.base.file.web.FileController {
	@Resource(name = "fileMapper")
	private FileMapper fileMapper;
	@Resource(name="fileBean")
	private FileBean fileBean;

    @Override
    public ModelAndView getFileList(FileQuery req) {
    	List<DataObject> fileInfoList = fileService().getFileList(req);

		return setPagingInfo(new ModelAndView("jsonView"), fileInfoList, "file");
    }

    /** 메뉴얼을 다운로드한다.
	 * @return 메뉴얼 파일
     * @throws Exception
	 */
    @GetMapping(name = "메뉴얼 다운로드", value = "/downloadMenual.do")
	public ModelAndView downloadMenual() throws Exception {
    	String filePath = ("menual/메뉴얼.pptx");
		ClassPathResource cps = new ClassPathResource(filePath);
		String menualVersion = "";
		try (XMLSlideShow slideShow = new XMLSlideShow(cps.getInputStream())) {
			menualVersion = slideShow
				.getProperties()
				.getCoreProperties()
				.getUnderlyingProperties()
				.getVersionProperty()
				.get();
		}

		InputStream menualIS = cps.getInputStream();
		byte[] menualBytes = menualIS.readAllBytes();
		menualIS.close();

		Consumer<OutputStream> writer = new Consumer<OutputStream>() {
			@Override
			public void accept(OutputStream os) {
				try {
					os.write(menualBytes);
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		};

		return new ModelAndView("downloadView")
			.addObject("download",
				new Downloadable()
					.setContentType("application/vnd.openxmlformats-officedocument.presentationml.presentation")
					.setWriter(writer)
					.setFilename("과태료통합관리시스템_메뉴얼"+"("+"v"+menualVersion+")"+".pptx")
		);
	}

	@GetMapping(name = "SVG 이미지 파일 색상 변경", value = "/modifySvg/**")
	public void modifySvg(HttpServletRequest request, HttpServletResponse response) throws URISyntaxException, IOException, ParserConfigurationException, SAXException {
        String requestURI = request.getRequestURI().toString();

        String filepath = requestURI.split("modifySvg")[1];
        filepath = URLDecoder.decode(filepath, "UTF-8");
        filepath = filepath.replaceAll("/", Matcher.quoteReplacement(File.separator));
        filepath = "svg" + filepath;

        InputStream is = new ClassPathResource(filepath).getInputStream();

        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder documentBuilder = factory.newDocumentBuilder();
        Document document = documentBuilder.parse(is);
        Element root = document.getDocumentElement();
        NodeList nodeList = root.getChildNodes();

        try {
            String modify = request.getParameter("modify");
            if(isEmpty(modify)){
            } else if(modify.equals("active")){
               updateTagFillColor(nodeList, "green");
            } else if(modify.equals("alert")){
               updateTagFillColor(nodeList, "red");
            }

            String str4 = DocumentToString(document);
            byte[] bytes = str4.getBytes();

            response.setHeader(HttpHeaders.ACCEPT_RANGES, "bytes");
            response.setHeader(HttpHeaders.CONTENT_TYPE, "image/svg+xml");
            response.setHeader(HttpHeaders.CONNECTION, "keep-alive");
            response.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
            response.setHeader("Pragma", "no-cache");
            response.setHeader(HttpHeaders.CACHE_CONTROL, "no-cache, must-revalidate");
            response.setDateHeader(HttpHeaders.EXPIRES, 0);
            response.setHeader(HttpHeaders.CONTENT_LENGTH, Integer.toString(bytes.length));
            response.setContentType("image/svg+xml");

            OutputStream os = response.getOutputStream();
            os.write(bytes);
            os.flush();
            os.close();
        } catch (Exception e){
        }
    }

    public static String DocumentToString( Document doc ) {
        try {
            StringWriter clsOutput = new StringWriter( );
            Transformer clsTrans = TransformerFactory.newInstance( ).newTransformer( );

            clsTrans.setOutputProperty( OutputKeys.OMIT_XML_DECLARATION, "no" );
            clsTrans.setOutputProperty( OutputKeys.METHOD, "xml" );
            clsTrans.setOutputProperty( OutputKeys.INDENT, "yes" );
            clsTrans.setOutputProperty( OutputKeys.ENCODING, "UTF-8" );

            clsTrans.transform( new DOMSource( doc ), new StreamResult( clsOutput ) );

            return clsOutput.toString( );
        } catch( Exception ex ) {
            return "";
        }
    }

    private void updateTagFillColor(NodeList nodeList, String newFillColor) {
        for (int i = 0; i < nodeList.getLength(); i++) {
            Node node = nodeList.item(i);
            NamedNodeMap namedNodeMap = node.getAttributes();
            if(namedNodeMap != null && namedNodeMap.getLength() > 0){
                for (int j = 0; j < namedNodeMap.getLength(); j++) {
                    Node namedNode = namedNodeMap.item(j);
                    if (namedNode.getNodeName().equalsIgnoreCase("fill")) {
                        namedNode.setNodeValue(newFillColor); // Change the color of the fill attribute.
                    }
                }
            }
        }
    }

    @PostMapping(name = "처리 전 파일업로드", value = "/uploadBeforeProcess.do")
    public ModelAndView uploadBeforeProcess(MultipartFile[] uploadFiles) {
    	MultipartFile uploadFile = uploadFiles[0];
    	String orginalFileName = uploadFile.getOriginalFilename();
    	String extension = FilenameUtils.getExtension(orginalFileName);

    	SimpleDateFormat ymdhmsFormat = new SimpleDateFormat("yyyyMMddHHmmss");
		String currentTime = ymdhmsFormat.format(new Date());

		String folderPath = "files/temp/uploadFirst";
		File folder = new File(folderPath);
		folder.mkdirs();
		String filePath = folderPath + "/"+currentTime+"."+extension;
    	File file = new File(filePath);

    	try {
			uploadFile.transferTo(file);
			return new ModelAndView("jsonView")
				.addObject("saved", true)
	    		.addObject("filePath", filePath);
		} catch (IOException e) {
			throw new RuntimeException("파일업로드 오류"+e);
		}
    }
}