package org.baderlab.lola.model;

import org.baderlab.brain.*;
import org.baderlab.lola.LolaParameterSet;
import org.baderlab.lola.resources.LolaResources;

import javax.imageio.ImageIO;
import java.io.*;
//import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.*;
//import java.awt.*;

import com.lowagie.text.pdf.*;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Rectangle;
import com.lowagie.text.Image;

/**
 Copyright 2007 Bader Lab

 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU Lesser General Public License as published by
 the Free Software Foundation; either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.

 */

/**
 * Container for various logo generation operations, inputs, and results.
 * User: moyez
 * Date: May 25, 2007
 * Time: 6:02:06 PM
 */


public class LogoGenerator {

    //write sequence logos for given profiles (adapted from BrainAlgorithm.writeSequenceLogos)
    public static BufferedImage generateImage(ProteinProfile proteinProfile,
                                          LolaParameterSet params,
                                          String fileSuffix) {


        //make the logo - disable trimming if trim % is 0
        ProteinSequenceLogo logo;
        if (params.getLogoTrimPercentage() == 0) {
            logo = new ProteinSequenceLogo(proteinProfile,
                    params.getLogoHeight(),
                    params.getDrawAxisLabels());
        }
        else {
            logo = new ProteinSequenceLogo(
                    proteinProfile,
                    params.getLogoTrimPercentage(),
                    params.getLogoHeight(),
                    params.getDrawAxisLabels());
        }
        
        logo.sequenceLogoSetStartIndex(params.getLogoStartIndex());
        BufferedImage image = logo.drawSequenceLogo(params.getAminoAcidGrouping().getProteinLogoStyle());

        return image;
    }

    //write sequence logos for given profiles (adapted from BrainAlgorithm.writeSequenceLogos)
    public static void writeLogo(Profile profile,
                                          LolaParameterSet params,
                                          String fileSuffix) {

        //if no suffix given, make it an empty string
        String suffix = fileSuffix;
        if (suffix == null) {
            suffix = "";
        }

        String fileExtension = null;
        String formatName = null;
        String imageFormat = params.getLogoImageFileFormat();
        if (imageFormat == null) {
            imageFormat = LolaResources.LOGO_IMAGE_FORMAT_DEFAULT;
        }
        if (imageFormat.equalsIgnoreCase(LolaResources.IMAGE_FORMAT_BMP)) {
            formatName = "bmp";
            fileExtension = "bmp";
        }
        else if (imageFormat.equalsIgnoreCase(LolaResources.IMAGE_FORMAT_JPG)) {
            formatName = "jpg";
            fileExtension = "jpg";
        }
        else if (imageFormat.equalsIgnoreCase(LolaResources.IMAGE_FORMAT_PNG)) {
            formatName = "png";
            fileExtension = "png";
        }
        else if (imageFormat.equalsIgnoreCase(LolaResources.IMAGE_FORMAT_PDF)) {
            formatName = "pdf";
            fileExtension = "pdf";
        }
        else {
            //This shouldn't happen
            System.out.println("Unexpected image file format: " + imageFormat);
            throw new IllegalStateException();
        }

        //construct output file name
        String outFileName = params.getOutputPath()
                + File.separator
                + profile.getName()
                + suffix
                + "."
                + fileExtension;


        //get image
        BufferedImage image = profile.getImage();
        if (image == null) {
            System.out.println("Unexpected null image in LogoGenerator.writeLogo.");
            throw new IllegalStateException();
        }


        //write to file
        try {
            if (imageFormat.equalsIgnoreCase(LolaResources.IMAGE_FORMAT_PDF)) {

                OutputStream out = new BufferedOutputStream(new FileOutputStream(new File(outFileName)));
                saveLogoAsPDF(profile.getProteinProfile(), params, out);
            }
            else {
                ImageIO.write(image, formatName, new File(outFileName));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

     private static void writeImageAsPDF(OutputStream out,
                                        BufferedImage logoImage,
                                        int width,
                                        int height,
                                        FontMapper mapper) throws IOException {

         Rectangle pagesize = new Rectangle(width, height);
         Document document = new Document(pagesize, 50, 50, 50, 50);

         try {
             PdfWriter writer = PdfWriter.getInstance(document, out);
             document.open();
             PdfContentByte cb = writer.getDirectContent();

             Image itextImage = Image.getInstance(logoImage, null);
             itextImage.setAbsolutePosition(0,0);
             //cb.addImage(itextImage);
             
             PdfTemplate tp = cb.createTemplate(width, height);
             
             tp.addImage(itextImage);
             cb.addTemplate(tp, 38, writer.getVerticalPosition(true)-height);
             //cb.addTemplate(tp, 0, 0);
         }
         catch (DocumentException de) {
             System.err.println(de.getMessage());
         }
         document.close();
     }

     /**
      * Save the string output to the specified file
      **/
     public static void saveToTextFile(File file, String output) throws IOException
     {
         BufferedWriter bw = new BufferedWriter(new FileWriter (file));
         bw.write(output);
         bw.close();
     }

     public static void saveImageAsPDF(File file,
                                       BufferedImage logoImage,
                                       int width,
                                       int height,
                                       FontMapper mapper) throws IOException {
             OutputStream out = new BufferedOutputStream(new
                     FileOutputStream(file));
         writeImageAsPDF(out, logoImage, width, height, mapper);
         out.close();
     }

    public static void saveLogoAsPDF(ProteinProfile proteinProfile, LolaParameterSet params, OutputStream out) {

        //make the logo - disable trimming if trim % is 0
        ProteinSequenceLogo logo;
        if (params.getLogoTrimPercentage() == 0) {
            logo = new ProteinSequenceLogo(proteinProfile,
                    params.getLogoHeight(),
                    params.getDrawAxisLabels());
        }
        else {
            logo = new ProteinSequenceLogo(
                    proteinProfile,
                    params.getLogoTrimPercentage(),
                    params.getLogoHeight(),
                    params.getDrawAxisLabels());
        }

        logo.sequenceLogoSetStartIndex(params.getLogoStartIndex());
        try {
            logo.saveAsPDF(out, params.getAminoAcidGrouping().getProteinLogoStyle());

        } catch (IOException e) {
            System.err.println(e.getMessage());
        }

    }


    public static void drawLogoTreeDrawAsPDF(OutputStream out,
                                       LogoTreeDraw ltd,
                                       int width,
                                       int height) throws IOException {

        com.lowagie.text.Rectangle pagesize = new com.lowagie.text.Rectangle(width, height);
        Document document = new Document(pagesize, 50, 50, 50, 50);

        try {
            PdfWriter writer = PdfWriter.getInstance(document, out);
            document.open();
            PdfContentByte cb = writer.getDirectContent();
            PdfTemplate tp = cb.createTemplate(width, height);

            Graphics2D graphics = tp.createGraphics(width, height, new DefaultFontMapper());
            ltd.draw(graphics);
            graphics.dispose();
            cb.addTemplate(tp, 0, 0);
        }
        catch (DocumentException de) {
            System.err.println(de.getMessage());
        }
        document.close();
    }


    public static void saveGraphicAsPDF(File file,
                                      LogoTreeDraw ltd,
                                      int width,
                                      int height) throws IOException {
            OutputStream out = new BufferedOutputStream(new
                    FileOutputStream(file));
        drawLogoTreeDrawAsPDF(out, ltd, width, height);
        out.close();
    }

}


