package gov.va.med.mpn.extract;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.StringReader;

import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

import org.apache.commons.lang3.text.WordUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

/**
 * The Class ExtractService. Implementation class for all Extract service calls.
 *
 * <p>
 * <A HREF="http://www.hp.com"> Hewlett-Packard Enterprise Services</A>
 * </p>
 *
 * @author <a href="mailto:pratap.chilukuri@hp.com">Pratap Chilukuri</a>
 */

@Path("/asciiservice/")
@Produces("text/xml")
@Service("extractService")
public class ExtractService {

	private final Logger slf4jLogger = LoggerFactory
			.getLogger(ExtractService.class);

	private void safeClose(PrintWriter pw) {

		if (pw != null) {
			// Note: PrintWriter closing does not need an IOException check
			pw.close();
		}

	}

	/**
	 * Extract xml.
	 *
	 * @param form
	 *            the ID of the form
	 * @param incomingData
	 *            xml data from formrunner submit
	 * @return response 200 for successful
	 */
	@POST
	@Path("/asciiextract/")
	@Consumes("*/*")
	public Response extractXml(@QueryParam("form") String form,
			InputStream incomingData) {

		String tagContent = null;
		String controlType = null;
		String controlName = null;
		String tagContentLabel = "";
		PrintWriter pw = null;

		StringBuilder crunchifyBuilder = new StringBuilder();
		try {
			BufferedReader in = new BufferedReader(new InputStreamReader(
					incomingData));
			String line = null;
			while ((line = in.readLine()) != null) {
				crunchifyBuilder.append(line);

			}

			Reader stringReader = new StringReader(crunchifyBuilder.toString());
			XMLInputFactory factory = XMLInputFactory.newInstance();
			// To fix potential XML External Entity injection attacks
			factory.setProperty(
					XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
			XMLStreamReader reader = factory
					.createXMLStreamReader(stringReader);

			try {
				// TODO: Change the filepath to actual path later
				pw = new PrintWriter(form + ".txt");

			} catch (FileNotFoundException ex) {

				slf4jLogger.error("Error Parsing: - " + ex.getMessage());
				return Response.status(500).build();

			} catch (SecurityException secx) {

				slf4jLogger.error("Error Parsing: - " + secx.getMessage());
				return Response.status(500).build();

			} finally {

				safeClose(pw);

			}

			while (reader.hasNext()) {
				int event = reader.next();

				switch (event) {
				case XMLStreamConstants.START_ELEMENT:
					controlName = reader.getLocalName();
					if ("control".equals(reader.getLocalName())) {
						controlType = reader.getAttributeValue(null, "type");
					}
					break;

				case XMLStreamConstants.CHARACTERS:

					String charText = reader.getText();

					if (charText != null) {

						tagContent = charText.trim();
						tagContent = tagContent.replaceAll("\\s+", " ").trim();

						if (controlName != null) {
							if ((!controlName.equals("hint"))
									&& (!controlName.equals("help"))) {

								if (!(tagContent.isEmpty())
										&& (controlName.equals("label"))) {

									tagContentLabel = tagContentLabel + " "
											+ tagContent;

								} else if (!(tagContent.isEmpty())
										&& (controlName.equals("value"))) {

									pw.print(":" + tagContent);

								} else {

									pw.print(WordUtils.wrap(tagContent, 255));

								}
							}
						}
					}

					break;

				case XMLStreamConstants.END_ELEMENT:

					switch (reader.getLocalName()) {
					case "control":
						pw.print("\n\n");
						controlType = null;
						break;
					case "label":
						if (tagContentLabel != null) {
							tagContent = tagContentLabel.replaceAll("\\<.*?>",
									"");
						}
						tagContentLabel = "";
						if ((controlType != null)
								&& (controlType.equals("section"))) {
							pw.print("-----------------------" + tagContent
									+ "-------------------------------------");
						} else {
							pw.print(WordUtils.wrap(tagContent, 255));
						}
						break;

					case "items":
						pw.print("\n     ");

					}
					break;

				case XMLStreamConstants.END_DOCUMENT:
					pw.close();
					break;
				}

			}

		} catch (IOException e) {

			slf4jLogger.error("Error Parsing: - " + e.getMessage());
			return Response.status(500).build();

		} catch (XMLStreamException xme) {

			slf4jLogger.error("Error Parsing: - " + xme.getMessage());
			return Response.status(500).build();

		} finally {

			safeClose(pw);

		}

		// return HTTP response 200 in case of success

		return Response.status(200).build();
	}

	// Write the parsed text from PDF to a file
	void writeTexttoFile(String pdfText, String fileName) {

		try {

			PrintWriter pw = new PrintWriter(fileName);
			pw.print(pdfText);
			pw.close();

		} catch (FileNotFoundException fioe) {

			slf4jLogger
					.error("An exception occured in writing the pdf text to file. "
							+ fioe.getMessage());

		} catch (SecurityException e) {

			slf4jLogger
					.error("An exception occured in writing the pdf text to file. "
							+ e.getMessage());

		}

	}

	final void init() {

	}

}