package info.bukova.isspst.reporting;

import info.bukova.isspst.storage.ReportFileStorage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;

@Controller
public class ReportController {
	
	@Autowired
	private ReportDefinition reportDefinition;
	@Autowired
	private GeneratorFactory factory;
	@Autowired
	private ParamFiller paramFiller;
	@Autowired
	private ReportFileStorage reportFileStorage;
	private static final String ERROR_MESSAGE = "<html><body><b>Generator returned no data!</b><br/>%s</body></html>";
	private final static Logger logger = LoggerFactory.getLogger(ReportController.class);
	
	private void writeError(OutputStream stream, Throwable e) {
		writeError(stream, e.toString());
	}
	
	private void writeError(OutputStream stream, String message) {
		String err =  String.format(ERROR_MESSAGE, message);
		try {
			stream.write(err.getBytes(), 0, err.getBytes().length);
		} catch (IOException e1) {
			e1.printStackTrace();
		}
	}
	
	@RequestMapping("report.pdf")
	public void pdfReport(HttpServletResponse response) {
		final String contentType = "application/pdf";
		
		ServletOutputStream os = null;
		
		try {
			os = response.getOutputStream();
			
			if ((reportDefinition.getReport() == null || reportDefinition.getDataSet() == null) && reportDefinition.getSignedDocItem() == null) {
				throw new ReportException("Definition is null");
			}

			byte[] data;

			if (reportDefinition.getSignedDocItem() == null) {
				paramFiller.fill();
				Generator gen = factory.createGenerator(reportDefinition);
				data = gen.generate();
			} else {
				data = reportFileStorage.fileData(reportDefinition.getSignedDocItem());
			}

			response.setContentType(contentType);
			response.setContentLength(data.length);
			
			os.write(data, 0, data.length);
			os.flush();
			os.close();
		} catch (IOException e) {
			logger.error("I/O error: " + e.getMessage());
		} catch (ReportException e) {
			logger.error("Report generation error: " + e.getMessage());
			writeError(os, e);
		} catch (Exception e) {
			logger.error("Report generation error: " + e.getMessage());
			writeError(os, e);
		} finally {
			if (os != null) {
				try {
					os.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

}
