//Copyright (C) 2003-2026, Foxit Software Inc..
//All Rights Reserved.
//
//http://www.foxitsoftware.com
//
//The following code is copyrighted and contains proprietary information and trade secrets of Foxit Software Inc..
//You cannot distribute any part of Foxit PDF SDK to any third party or general public,
//unless there is a separate license agreement with Foxit Software Inc. which explicitly grants you such rights.
// If using a stream to load the html file, set variable isfilestreamload to true.
//
//This file contains an example to demonstrate how to use Foxit PDF SDK to convert from html to pdf.

import com.foxit.sdk.PDFException;
import com.foxit.sdk.common.Library;
import com.foxit.sdk.common.fxcrt.RectF;
import com.foxit.sdk.pdf.PDFDoc;
import com.foxit.sdk.addon.conversion.HTML2PDFSettingData;
import com.foxit.sdk.common.fxcrt.FileReaderCallback;
import com.foxit.sdk.common.fxcrt.FileWriterCallback;
import com.foxit.sdk.addon.conversion.HTML2PDFRelatedResourceArray;
import com.foxit.sdk.addon.conversion.HTML2PDFRelatedResource;

import java.io.File;
import java.util.Date;
import java.util.Calendar;
import java.util.Random;
import java.io.*;

import static com.foxit.sdk.common.Constants.e_ErrSuccess;

public class html2pdf {
    private static String key = "8f3g1sFttW8NAgfSNv+BvaJWy4Pp8flcm7ncNDkdvCCO4JwUFbGLyZdujReMaiplbYJwwxam3lr7uHtQaEf0xTSu8j2ZBdrZ8FS4OQkEUjOI9UEGb3Ic0GqmlP9T9OnSItOYqoZZA/OnYg5EaVP+c/ha32nUquOk+5riEdhYgINAZDdgJkPc+YSWsrfixOIROf6t34j3eRcyFnOY0MS7tSXi1AEPE0VZdyu+5bfmBSGvLI+WR5lQ+oOQR5hRGwqf990WEdBelNO7dxhZELVhEZ+/L60PpDf5y9A8qmrY6PiEU8nhqIyLpks0BxeIsYyZ3Cr82jjfbItPGyEARsIVzluBSgVMD4oGjojz8T6wGDEXUbmZH/pra94XAs8wZ28mzbmIEppWnhBqX0c6Ov8iXCfFfUZr4KNuPxMEgk4VOYTMOd70GEjGnylivw18hbn7ZpkWh2Zql+uU2HejvOgn+WHvT0HF9NhK0Xb5vH8aFkgBP92PJx8obIbxBVeeExczxvsqWufuPdXS2sPNIgMYZ2TtvqVVsiUToeGB2FQo09fzZOSH5Vi18u/siyvC3FmjeMf4+OYWPuDPNCcrb21NgcHam7XI8AAoGLTGtLLWR+fxynbBBcg2d2ZPcZ5CMFIfOBHRWCkcA0sDT3cl9nsBppHNJze/jVxHy+lREeQEA/etSIgohTGAWW3ZlpibRXqMxlmVWEPifCubbWTzQ6U54mRMpW2UghH3gvCNFNgdday3Av7EtlIJOdUuiMq3zmmd5J4Jt4C82CKnVewA0DtZ4EEtwRG9IYuLrfpuZlnjBAtoeXRV1lqUZ6BcCe0E3m9jO28sGkALuIeJQ74XG7X8lMC7lMWWQYiYD7D6G9QT6X3qV4vXJwNKRKpYc/rI+amEawTSnDYAMEaYPwtZ0rb/7BL+atsZZaI+ncebdfVfjDJZbCZAc+JnkuNlUn2xrNRuObw8h/G0lm2pNOEJ10S8R4+yplo5B1QmC2dCDhaTaW67QJPqnJPKbVmjw7i6KGBi+CDP3JnAKlOX/YUu8uk56JfeQUuGcQg/KaBMGctnchH2n1i3+oGbibhurQj22+OO66Q6mijKoCRP/QJm5WTGcO4c0iVX0B8dIlai/uv/pGU8Wps9MxysH5ViVIj56LWKuNfy1FNO9+wx4iHYnUxfW0Iccq3YJYAlOBkMv8VZIJl9aTEEFJ626LJEw/UbEBdR9CdlwnylPf4RuNW/lcGYMgq3xNVpp/bzYKwZivvQOFgMdX1tv8D33SHvAm3zrRCU+v94BJXnBi9k25fnKsc705IMwv+I6bueXA+mDnagj1oTqsWXZ0WnPAYI3WUO7sBf7XUH230wfYXnTSVhujJxiEP/2oWqi2813gtQkKwz9N2p6yT8Vsh3+BaAwwDvtOZMJKUFcabTBSL6NoouzmzwItJ4mIboT6KXaef66rs8jCU=";;
    private static String sn = "Rew1vB0TqoMIxX444UcpScARWdhgJpsJfzmyMLR32a0+EgrCjp2NaQ==";

    private static String output_directory = "../output_files/html2pdf/";
    private static int timeout = 15;
	
	private static String url_or_html = "../input_files/AboutFoxit.html";
    // "engine_path" is the path of the engine file "fxhtml2pdf" which is used to convert html to pdf. Please refer to Developer Guide for more details.
    private static String engine_path = "";
    // "cookies_path" is the path of the cookies file exported from the web pages that you want to convert. Please refer to Developer Guide for more details.
    private static String cookies_path = "";
    private static String output_pdf_path = output_directory + "html2pdf_result.pdf";

    // You can also use System.load("filename") instead. The filename argument must be an absolute path name.
    static {
      String os = System.getProperty("os.name").toLowerCase();
      String lib = "fsdk_java_";
      if (os.startsWith("win")) {
          lib += "win";
      } else if (os.startsWith("mac")) {
          lib += "mac";
      } else {
          lib += "linux";
      }
        
      if (System.getProperty("sun.arch.data.model").equals("64")) {
        if(System.getProperty("os.arch").equals("aarch64")){
          if(os.startsWith("mac")){
             lib += "arm";
           }
           else{
             lib += "armv8";
           }
         }
         else{
            lib += "64";
         }
      } else {
         if(System.getProperty("os.arch").equals("arm")){
            lib += "armv7";
         }
         else{
            lib += "32";
         }
      }
      System.loadLibrary(lib);
    }
    private static void createResultFolder(String output_path) {
        File myPath = new File(output_path);
        if (!myPath.exists()) {
            myPath.mkdir();
        }
    }
	
	public static void main(String[] args) throws PDFException {
    	int length=args.length;
    	createResultFolder(output_directory);
        // Initialize library       
        if (length > 0 && args[0].equals("--help"))
        {
        	System.out.println("Usage:");
        	System.out.println("html2pdf_xxx <-html <The url or html path>> <-o <output pdf path>> <-engine <htmltopdf engine path>>");
        	System.out.println(" [-w <page width>] [-h <page height>]  [-r <page rotate degree>] [-mode <page mode>] [-scale <whether scale page>]");
        	System.out.println(" [-ml <margin left>] [-mr <margin right>] [-mt <margin top>] [-mb <margin bottom>] [-link <whether convert link>]");
        	System.out.println(" [-tag <whether generate tag>] [-bookmarks <whether to generate bookmarks>] [-cookies <cookies file path>] [-timeout <timeout>]\r\n\r\n");
        	System.out.println("-html The url or html file path. for examples '-html www.foxitsoftware.com'");
        	System.out.println("-o The output pdf path." );
        	System.out.println("-engine The html to pdf engine path.");
        	System.out.println("-w The page width.");
        	System.out.println("-h The page height.");
        	System.out.println("-r The page roate degree. '0' means 0 degree, '1' means 90 degree, '2' means 180 degree, '3' means 270 degree.");
			System.out.println("-ml The page margin distance of left.");
            System.out.println("-mr The page margin distance of right.");
            System.out.println("-mt The page margin distance of top.");
            System.out.println("-mb The page margin distance of bottom.");
        	System.out.println("-mode The page mode. 0 means single page mode and 1 means multiple mode");
        	System.out.println("-scale The scaling mode. '0' means no scale, '1' means scale page, '2' means enlarge page.");
        	System.out.println("-link Whether to covert link. 'yes' means to convert link, 'no' means no need to covert.");
        	System.out.println("-tag Whether to generate tag. 'yes' means to generate tag, 'no' means no need to generate.");
        	System.out.println("-bookmarks Whether to generate bookmarks.'yes' means generate bookmarks, 'no' means no need to generate.");
            System.out.println("-encoding The HTML encoding format. '0' means auto encoding and '1'-'73' means other encodings");
            System.out.println("-render_images Whether to render images or not.'yes' means to render images, 'no' means no need to render.");
            System.out.println("-remove_underline_for_link Whether to remove underline for link. 'yes' means to remove underline for link, 'no' means no need to remove.");
            System.out.println("-headerfooter Whether to generate headerfooter. 'yes' means to generate headerfooter, 'no' means no need to generate.");
            System.out.println("-headerfooter_title The headerfooter title.");
            System.out.println("-headerfooter_url The headerfooter url.");
            System.out.println("-bookmark_root_name The bookmark root name.");
            System.out.println("-resize_objects Whether to enable the Javascripts related resizing of the objects during rendering process. 'yes' means to enable, 'no' means to disable.");
            System.out.println("-print_background Whether to print background. 'yes' means to print background, 'no' means no need to print background.");
            System.out.println("-optimize_tag Whether to optimize tag tree. 'yes' means to optimize tag tree, 'no' means no need to optimize tag tree.");
            System.out.println("-media The media style. '0' means screen media style, '1' means print media style.");
        	System.out.println("-cookies The cookies file path.");
        	System.out.println("-timeout The timeout of loading webpages.");
        	return;
        }
        boolean isfilestreamload = false;
        int error_code = Library.initialize(sn, key);
        if (error_code != e_ErrSuccess) {
            System.out.println("Library Initialize Error: " + error_code);
            return;
        }

        try {
        	com.foxit.sdk.addon.conversion.HTML2PDFSettingData pdf_setting_data=new com.foxit.sdk.addon.conversion.HTML2PDFSettingData();	
        	pdf_setting_data.setIs_convert_link(true);
        	pdf_setting_data.setIs_generate_tag(true); 
        	pdf_setting_data.setTo_generate_bookmarks(true); 
        	pdf_setting_data.setRotate_degrees(0);    
        	pdf_setting_data.setPage_width(900);
        	pdf_setting_data.setPage_height(640);	
        	pdf_setting_data.setPage_mode(HTML2PDFSettingData.e_PageModeSinglePage); 
            pdf_setting_data.setScaling_mode(HTML2PDFSettingData.e_ScalingModeScale);
            pdf_setting_data.setTo_print_background(true);
            pdf_setting_data.setTo_optimize_tag_tree(false);
            pdf_setting_data.setMedia_style(HTML2PDFSettingData.e_MediaStyleScreen);
    		
			if (!AnalysisParameter(length, args, pdf_setting_data)) return;
    		com.foxit.sdk.addon.conversion.Convert.fromHTML(url_or_html, engine_path, cookies_path, pdf_setting_data, output_pdf_path, timeout);
            System.out.println("Convert HTML to PDF successfully!");

        } catch (Exception e) {
            e.printStackTrace();
        }
        if(isfilestreamload){
            try {
                  com.foxit.sdk.addon.conversion.HTML2PDFSettingData pdf_setting_data=new com.foxit.sdk.addon.conversion.HTML2PDFSettingData();   
                  pdf_setting_data.setPage_height(650);
                  pdf_setting_data.setPage_width(950);
                  pdf_setting_data.setIs_to_page_scale(false);
                  pdf_setting_data.setPage_margin(new RectF(18, 18, 18, 18));
                  pdf_setting_data.setIs_convert_link(true);
                  pdf_setting_data.setRotate_degrees(0);
                  pdf_setting_data.setIs_generate_tag(true);
                  pdf_setting_data.setPage_mode(HTML2PDFSettingData.e_PageModeSinglePage); 
                  pdf_setting_data.setScaling_mode(HTML2PDFSettingData.e_ScalingModeScale);
                  pdf_setting_data.setTo_generate_bookmarks(true);
                  pdf_setting_data.setEncoding_format(0);
                  pdf_setting_data.setTo_render_images(true);
                  pdf_setting_data.setTo_remove_underline_for_link(false);
                  pdf_setting_data.setTo_set_headerfooter(false);
                  pdf_setting_data.setHeaderfooter_title("");
                  pdf_setting_data.setHeaderfooter_url("");
                  pdf_setting_data.setBookmark_root_name("abcde");
                  pdf_setting_data.setTo_resize_objects(true);
                  pdf_setting_data.setTo_print_background(false);
                  pdf_setting_data.setTo_optimize_tag_tree(false);
                  pdf_setting_data.setMedia_style(0);
                  pdf_setting_data.getTo_load_active_content();
                  String output_path = output_directory + "html2pdf_filestream_result.pdf";
                  FoxitFileWriter filewrite = new FoxitFileWriter();
                  filewrite.LoadFile(output_path);
                  // "htmlfile" is the path of the html file to be loaded. For example: "C:/aaa.html". The method of "FromHTML" will load this file as a stream.
                  String htmlfile = "";
                  FileRead filereader = new FileRead();
                  filereader.loadFile(htmlfile,false);

                  //"htmlfilepng" is the path of the png resource file to be loaded. For example: "C:/aaa.png". set "htmlfilepng" in the related_resource_file of HTML2PDFRelatedResource.
                  String htmlfilepng ="";
                  FileRead filereader1 = new FileRead();
                  filereader1.loadFile(htmlfilepng,false);
                  //"relativefilepath" is  the resource file's relative path. For example: "./aaa.png".
                  String relativefilepath = "";
                  com.foxit.sdk.addon.conversion.HTML2PDFRelatedResourceArray html2PDFRelatedResourceArray = new com.foxit.sdk.addon.conversion.HTML2PDFRelatedResourceArray();
                  com.foxit.sdk.addon.conversion.HTML2PDFRelatedResource html2PDFRelatedResource = new com.foxit.sdk.addon.conversion.HTML2PDFRelatedResource(filereader1,relativefilepath);

                  html2PDFRelatedResourceArray.add(html2PDFRelatedResource);
                  com.foxit.sdk.addon.conversion.Convert.fromHTML(filereader, html2PDFRelatedResourceArray, engine_path, null,
                                                              pdf_setting_data, filewrite, 30);
                  System.out.println("Convert HTML to PDF successfully by filestream!");

            } catch (Exception e) {
                e.printStackTrace();
            }            
        }


        Library.release();
    }

    static boolean AnalysisParameter(int length, String[] args, HTML2PDFSettingData pdf_setting_data)
    {
    	for (int i = 0; i < length; i = i + 2) {
    		String args_key = args[i];
    		String args_value;
    		if (length <= i + 1) {
			  System.out.println("Please make sure the key " + args_key + " is valid and it has value!\n");
			  System.out.println("Usage: html2pdf_xxx <-html <The url or html path>> <-o <output pdf path>> ...\nPlease try 'html2pdf_xxx --help' for more information.\n");
			  return false;
			};
    		args_value = (args[i + 1]);
    		if (args_key.equals("-w")) pdf_setting_data.setPage_width(Float.parseFloat(args_value)) ;
    		else if (args_key.equals("-h")) pdf_setting_data.setPage_height(Float.parseFloat(args_value));
    		else if (args_key.equals("-r")) pdf_setting_data.setRotate_degrees(Integer.parseInt(args_value));
    		else if (args_key.equals("-ml")) {
				pdf_setting_data.getPage_margin().setLeft(Float.parseFloat(args_value));
			}
    		else if (args_key.equals("-mr")) {
				pdf_setting_data.getPage_margin().setRight(Float.parseFloat(args_value));
			}
    		else if (args_key.equals("-mt")) {
				pdf_setting_data.getPage_margin().setTop(Float.parseFloat(args_value));
			}
    		else if (args_key.equals("-mb")) {
				pdf_setting_data.getPage_margin().setBottom(Float.parseFloat(args_value));
			}
    		else if (args_key.equals("-scale")) pdf_setting_data.setScaling_mode(Integer.parseInt(args_value));
    		else if (args_key.equals("-link")) pdf_setting_data.setIs_convert_link (args_value.equalsIgnoreCase("yes") ? true : false);
    		else if (args_key.equals("-tag")) pdf_setting_data.setIs_generate_tag(args_value.equalsIgnoreCase("yes") ? true : false);
    		else if (args_key.equals("-bookmarks")) pdf_setting_data.setTo_generate_bookmarks(args_value.equalsIgnoreCase("yes") ? true : false);
    		else if (args_key.equals("-mode")) pdf_setting_data.setPage_mode(Integer.parseInt(args_value));
            else if (args_key.equals("-encoding")) pdf_setting_data.setEncoding_format(Integer.parseInt(args_value));
            else if (args_key.equals("-render_images")) pdf_setting_data.setTo_render_images(args_value.equalsIgnoreCase("yes") ? true : false);
            else if (args_key.equals("-remove_underline_for_link")) pdf_setting_data.setTo_remove_underline_for_link(args_value.equalsIgnoreCase("yes") ? true : false);
            else if (args_key.equals("-headerfooter")) pdf_setting_data.setTo_set_headerfooter(args_value.equalsIgnoreCase("yes") ? true : false);
            else if (args_key.equals("-headerfooter_title")) pdf_setting_data.setHeaderfooter_title(args_value);
            else if (args_key.equals("-headerfooter_url")) pdf_setting_data.setHeaderfooter_url(args_value);
            else if (args_key.equals("-bookmark_root_name")) pdf_setting_data.setBookmark_root_name(args_value);
            else if (args_key.equals("-resize_objects")) pdf_setting_data.setTo_resize_objects(args_value.equalsIgnoreCase("yes") ? true : false);
		    else if (args_key.equals("-print_background")) pdf_setting_data.setTo_print_background(args_value.equalsIgnoreCase("yes") ? true : false);
		    else if (args_key.equals("-optimize_tag")) pdf_setting_data.setTo_print_background(args_value.equalsIgnoreCase("yes") ? true : false);
		    else if (args_key.equals("-media")) pdf_setting_data.setMedia_style(Integer.parseInt(args_value));
    		else if (args_key.equals("-engine")) engine_path = args_value;
    		else if (args_key.equals("-cookies")) cookies_path = args_value;
    		else if (args_key.equals("-o")) output_pdf_path = args_value;
    		else if (args_key.equals("-html")) url_or_html = args_value;
    		else if (args_key.equals("-timeout")) timeout = Integer.parseInt(args_value);
			else {
				System.out.println("Please make sure the key " + args_key + " is valid and it has value!\n");
				System.out.println("Usage: html2pdf_xxx <-html <The url or html path>> <-o <output pdf path>> ...\nPlease try 'html2pdf_xxx --help' for more information.\n");
				return false;
			}
    	} 	
		return true;
    }
}


class FileRead extends FileReaderCallback {
    private RandomAccessFile file_ = null;
    private boolean is_large_file_ = false;

    FileRead() {

    }

    public boolean loadFile(String file_path, boolean is_large_file) throws FileNotFoundException {
        this.is_large_file_ = is_large_file;
        file_ = new RandomAccessFile(file_path, "r");
        return true;

    }

    @Override
    public long getSize() {
        try {
            return this.file_.length();
        } catch (IOException e) {
            e.printStackTrace();
        } 
        return 0;
    }

    @Override
    public boolean readBlock(byte[] buffer, long offset, long size) {
      try {
            file_.seek(offset);
            int read = file_.read(buffer, 0, (int) size);
            return read == size ? true : false;
        } catch (IOException e) {
            e.printStackTrace();
        }
      return false;
    }

    @Override
    public void release() {
        try {
             this.file_.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

class FoxitFileWriter extends FileWriterCallback {
    private RandomAccessFile file_ = null;

    boolean LoadFile(String file_path) throws FileNotFoundException {
        File path_file = new File(file_path);
        if(path_file.exists() == true) path_file.delete();
        file_ = new RandomAccessFile(file_path, "rw");
        return true;
    }

    @Override
    public long getSize() {
        try {
            return this.file_.length();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return 0;
    }

    @Override
    public boolean writeBlock(byte[] buffer, long offset, long size) {
        try {
            file_.seek(offset);
            file_.write(buffer, 0, (int) size);
            return true;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }

    public boolean writeBlock(byte[] buffer, long size) {
        return writeBlock(buffer, getSize(), size);
    }

    @Override
    public boolean flush() {
        return true;
    }
    
    public void release() {
        try {
            this.file_.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}