package com.jasamedika.medifirst2000.controller;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.orm.jpa.JpaSystemException;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.itextpdf.text.BadElementException;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.pdf.codec.Base64;
import com.itextpdf.tool.xml.XMLWorker;
import com.itextpdf.tool.xml.XMLWorkerHelper;
import com.itextpdf.tool.xml.html.Tags;
import com.itextpdf.tool.xml.parser.XMLParser;
import com.itextpdf.tool.xml.pipeline.css.CSSResolver;
import com.itextpdf.tool.xml.pipeline.css.CssResolverPipeline;
import com.itextpdf.tool.xml.pipeline.end.PdfWriterPipeline;
import com.itextpdf.tool.xml.pipeline.html.AbstractImageProvider;
import com.itextpdf.tool.xml.pipeline.html.HtmlPipeline;
import com.itextpdf.tool.xml.pipeline.html.HtmlPipelineContext;
import com.jasamedika.medifirst2000.constants.Constants;
import com.jasamedika.medifirst2000.controller.base.LocaleController;
import com.jasamedika.medifirst2000.exception.ServiceVOException;
import com.jasamedika.medifirst2000.util.rest.RestUtil;
import com.jasamedika.medifirst2000.vo.PemakaianAsuransiVO;

class Base64ImageProvider extends AbstractImageProvider {
	 
    @Override
    public Image retrieve(String src) {
        int pos = src.indexOf("base64,");
        try {
            if (src.startsWith("data") && pos > 0) {
                byte[] img = Base64.decode(src.substring(pos + 7));
                return Image.getInstance(img);
            }
            else {
            	 
                return Image.getInstance(src);
            }
        } catch (BadElementException ex) {
            return null;
        } catch (IOException ex) {
            return null;
        }
    }

    @Override
    public String getImageRootPath() {
        return null;
    }
}

@RestController
@RequestMapping("/html-to-pdf")
public class HtmlToPdfController extends LocaleController {

	private static final Logger LOGGER = LoggerFactory.getLogger(HtmlToPdfController.class);

	@RequestMapping(value = "/get-pdf", method = RequestMethod.GET)
	public ResponseEntity<String> getAllVOWithQueryString(HttpServletRequest request, HttpServletResponse response,
			@RequestParam(value = "url") String url, @RequestParam(value = "fileName") String fileName) {

		try {
			createPDF(fileName, url, request, response);
			return RestUtil.getJsonResponse("", HttpStatus.CREATED, mapHeaderMessage);
		} catch (ServiceVOException e) {
			LOGGER.error("Got exception {} when add Agama", e.getMessage());
			addHeaderMessage(Constants.MessageInfo.ERROR_MESSAGE, e.getMessage());
			return RestUtil.getJsonHttptatus(HttpStatus.INTERNAL_SERVER_ERROR, mapHeaderMessage);
		} catch (JpaSystemException jse) {
			LOGGER.error("Got exception {} when add Agama", jse.getMessage());
			addHeaderMessage(Constants.MessageInfo.ERROR_MESSAGE, jse.getMessage());
			return RestUtil.getJsonHttptatus(HttpStatus.CONFLICT, mapHeaderMessage);
		}
	}

	@RequestMapping(value = "/post-pdf", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
	public ResponseEntity<String> postPdf(HttpServletRequest request, HttpServletResponse response,
			@RequestParam(value = "url") String url, @RequestParam(value = "fileName") String fileName) {

		try {
			BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream()));

			String read = null;
			String resultData = "";
			while ((read = reader.readLine()) != null) {
				resultData += read;
				System.out.println(read);
			}
			InputStream is = new ByteArrayInputStream(resultData.getBytes());
			createPDF(fileName, url, resultData, request, response);
			return RestUtil.getJsonResponse("", HttpStatus.CREATED, mapHeaderMessage);
		} catch (ServiceVOException e) {
			LOGGER.error("Got exception {} when add Agama", e.getMessage());
			addHeaderMessage(Constants.MessageInfo.ERROR_MESSAGE, e.getMessage());
			return RestUtil.getJsonHttptatus(HttpStatus.INTERNAL_SERVER_ERROR, mapHeaderMessage);
		} catch (JpaSystemException jse) {
			LOGGER.error("Got exception {} when add Agama", jse.getMessage());
			addHeaderMessage(Constants.MessageInfo.ERROR_MESSAGE, jse.getMessage());
			return RestUtil.getJsonHttptatus(HttpStatus.CONFLICT, mapHeaderMessage);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return RestUtil.getJsonHttptatus(HttpStatus.INTERNAL_SERVER_ERROR);
	}

	private void createPDF(String pdfFilename, String url, HttpServletRequest request, HttpServletResponse response) {

		// path for the PDF file to be generated
		String dataDirectory = request.getServletContext().getRealPath("/WEB-INF/downloads/pdf/" + pdfFilename);
		PdfWriter pdfWriter = null;

		// create a new document
		Document document = new Document();

		try {

			// get Instance of the PDFWriter
			pdfWriter = PdfWriter.getInstance(document, new FileOutputStream(dataDirectory));

			// document header attributes
			document.addAuthor("betterThanZero");
			document.addCreationDate();
			document.addProducer();
			document.addCreator("MySampleCode.com");
			document.addTitle("Demo for iText XMLWorker");
			document.setPageSize(PageSize.LETTER);

			// open document
			document.open();

			// To convert a HTML file from the filesystem
			// String File_To_Convert = "docs/SamplePDF.html";
			// FileInputStream fis = new FileInputStream(File_To_Convert);

			// URL for HTML page
			URL myWebPage = new URL(url);
			InputStreamReader fis = new InputStreamReader(myWebPage.openStream());

			// get the XMLWorkerHelper Instance
			XMLWorkerHelper worker = XMLWorkerHelper.getInstance();

			// convert to PDF
			worker.parseXHtml(pdfWriter, document, fis);

			// close the document
			document.close();
			// close the writer
			pdfWriter.close();

		}

		catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (DocumentException e) {
			e.printStackTrace();
		}

		String dataDirectoryDownload = request.getServletContext().getRealPath("/WEB-INF/downloads/pdf/");
		Path file = Paths.get(dataDirectoryDownload, pdfFilename);
		if (Files.exists(file)) {
			response.setContentType("application/pdf");
			response.addHeader("Content-Disposition", "attachment; filename=" + pdfFilename);
			try {
				Files.copy(file, response.getOutputStream());
				response.getOutputStream().flush();
			} catch (IOException ex) {
				ex.printStackTrace();
			}
		}

	}

	private void createPDF(String pdfFilename, String url, String inputStream, HttpServletRequest request,
			HttpServletResponse response) {

		// path for the PDF file to be generated
		String dataDirectory = request.getServletContext().getRealPath("/WEB-INF/downloads/pdf/" + pdfFilename);
		PdfWriter pdfWriter = null;

		// create a new document
		Document document = new Document();

		try {

			 
		        // step 2
		        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(dataDirectory));
		        // step 3
		        document.open();
		        // step 4
		 
		        // CSS
		        CSSResolver cssResolver =
		                XMLWorkerHelper.getInstance().getDefaultCssResolver(true);
		 
		        // HTML
		        HtmlPipelineContext htmlContext = new HtmlPipelineContext(null);
		        htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory());
		        htmlContext.setImageProvider(new Base64ImageProvider());
		 
		        // Pipelines
		        PdfWriterPipeline pdf = new PdfWriterPipeline(document, writer);
		        HtmlPipeline html = new HtmlPipeline(htmlContext, pdf);
		        CssResolverPipeline css = new CssResolverPipeline(cssResolver, html);
		 
		        // XML Worker
		        XMLWorker worker = new XMLWorker(css, true);
		        XMLParser p = new XMLParser(worker);
		        p.parse(new ByteArrayInputStream(inputStream.getBytes()));
		 
		        // step 5
		        document.close();

		}

		catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (DocumentException e) {
			e.printStackTrace();
		}

		String dataDirectoryDownload = request.getServletContext().getRealPath("/WEB-INF/downloads/pdf/");
		Path file = Paths.get(dataDirectoryDownload, pdfFilename);
		if (Files.exists(file)) {
			response.setContentType("application/pdf");
			response.addHeader("Content-Disposition", "attachment; filename=" + pdfFilename);
			try {
				Files.copy(file, response.getOutputStream());
				response.getOutputStream().flush();
			} catch (IOException ex) {
				ex.printStackTrace();
			}
		}

	}

}
