// 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.
//
// This file contains an example to demonstrate how to use Foxit PDF SDK to create or open a portfolio PDF file.

using System;
using System.Text;
using System.IO;

using foxit;
using foxit.common;
using foxit.common.fxcrt;
using foxit.pdf;
using foxit.pdf.actions;

namespace portfolioCS
{
    class TextDoc 
    {
        private FileStream mfile_stream;
        public TextDoc(string file_name, FileMode fill_mode)
        {
            mfile_stream = new FileStream(file_name, fill_mode);
        }
        ~TextDoc()
        {
            try
            {
                mfile_stream.Flush();
                mfile_stream.Close();
            }
            catch (System.ObjectDisposedException e)
            {
                string str = e.Message;
            }
            
        }
        public void Write(string contents)
        {
            byte[] byte_data = Encoding.Default.GetBytes(contents);
            // Move file pointer to the end of file.
            mfile_stream.Seek(0, SeekOrigin.End);
            mfile_stream.Write(byte_data, 0, byte_data.Length);
            mfile_stream.Flush();
        }
        public string Read()
        {
            int fs_len = (int)mfile_stream.Length;
            byte[] byte_data = new byte[fs_len];
            int r = mfile_stream.Read(byte_data, 0, byte_data.Length);
            string contents = System.Text.Encoding.UTF8.GetString(byte_data);
            return contents;
        }
    };

    class portfolio
    {
        private static string input_path = "../input_files/";

        public static bool CreatPortfolioPDF(string saved_portfolio_pdf_path) {
            // Create a new blank portfolio PDF.
            using (Portfolio new_portfolio = Portfolio.CreatePortfolio()) {
                if (true == new_portfolio.IsEmpty()) {
                    Console.WriteLine("[FAILED] Fail to create a new portfolio PDF.\r\n");
                    return false;
                }

                // Get the root node.
                using (PortfolioNode root_node = new_portfolio.GetRootNode()) {
                    if (true == root_node.IsEmpty()) {
                        Console.WriteLine("[FAILED] Fail to get the root node.\r\n");
                        return false;
                    }
                    // The root node should be a folder node, so transfer to use PortfolioFolderNode.
                    using (PortfolioFolderNode root_folder = new PortfolioFolderNode(root_node))
                    {

                        // Pre-load the PDF file which is to be added to new sub folder in portfolio PDF.
                        // ATTENTION: please keep the PDF document object valid until portfolio PDF is saved or ends its life-cycle.
                        string input_pdf_filename = "AboutFoxit.pdf";
                        string input_pdf_file_path = input_path + input_pdf_filename;
                        using (PDFDoc pdf_doc = new PDFDoc(input_pdf_file_path))
                        {
                            ErrorCode error_code = pdf_doc.Load(null);
                            if (error_code != ErrorCode.e_ErrSuccess)
                            {
                                Console.WriteLine("[FAILED] Fail to load PDF file {0}. Error: {1}\n", input_pdf_file_path, error_code);
                            }

                            // Add a sub folder to root folder node.
                            using (PortfolioFolderNode new_sub_foldernode = root_folder.AddSubFolder("Sub Folder-1"))
                            {
                                if (true == new_sub_foldernode.IsEmpty())
                                {
                                    Console.WriteLine("[FAILED] Fail to add sub folder.\r\n");
                                }
                                else
                                {
                                    new_sub_foldernode.SetDescription("This is a sub folder added to portfolio PDF file.");

                                    if (false == pdf_doc.IsEmpty())
                                    {
                                        // Add a valid PDF document object to current folder node.
                                        // ATTENTION: please keep the PDF document object valid until portfolio PDF is saved or ends its life-cycle.
                                        using (PortfolioFileNode new_filenode = new_sub_foldernode.AddPDFDoc(pdf_doc, input_pdf_filename))
                                        {
                                            if (true == new_filenode.IsEmpty())
                                            {
                                                Console.WriteLine("[FAILED] Fail to add PDF file {0}.\r\n", input_pdf_file_path);
                                            }
                                            else
                                            {
                                                using (FileSpec file_spec = new_filenode.GetFileSpec())
                                                {
                                                    file_spec.SetDescription("This is a common PDF file added to portfolio PDF file");
                                                }
                                            }
                                        }
                                    }
                                }
                            }


                            // Add a non-PDF file to root folder node.
                            string input_file_path = input_path + "FoxitLogo.jpg";
                            using (PortfolioFileNode new_sub_filenode = root_folder.AddFile(input_file_path))
                            {
                                if (true == new_sub_filenode.IsEmpty())
                                {
                                    Console.WriteLine("[FAILED] Fail to add file {0}.\r\n", input_file_path);
                                }
                                else
                                {
                                    using (FileSpec file_spec = new_sub_filenode.GetFileSpec())
                                    {
                                        file_spec.SetDescription("This is a non-PDF file added to portfolio PDF file.");
                                    }
                                }
                            }

                            // User can update schema field and other properties by class Portfolio, if necessary.

                            // Save the new portfolio PDF file.
                            using (PDFDoc portfolio_pdf_doc = new_portfolio.GetPortfolioPDFDoc())
                            {
                                if (true == portfolio_pdf_doc.IsEmpty())
                                {
                                    Console.WriteLine("[FAILED] Fail to get portfolio PDF document object.\r\n");
                                    return false;
                                }
                                else
                                {
                                    return portfolio_pdf_doc.SaveAs(saved_portfolio_pdf_path, (int)PDFDoc.SaveFlags.e_SaveFlagNormal);
                                }
                            }
                        }
                    }
                }
            }
        }
        public static void OutputTab(TextDoc output_txt_doc, int nTabCount)
        {
            for (int i = 0; i < nTabCount; i++)
                output_txt_doc.Write("\t");
        }

        public static void OutputFileNodeInfo(TextDoc output_txt_doc, PortfolioFileNode node, int tab_count) {
            if (tab_count>0)
                OutputTab(output_txt_doc, tab_count);
            output_txt_doc.Write("Type:File\r\n");

            string key_name = node.GetKeyName();
            if (tab_count>0)
                OutputTab(output_txt_doc, tab_count);
            output_txt_doc.Write(string.Format("Key Name:{0}\r\n", key_name));

            using (FileSpec file_spec = node.GetFileSpec())
            {
                string file_name = file_spec.GetFileName();
                if (tab_count > 0)
                    OutputTab(output_txt_doc, tab_count);
                output_txt_doc.Write(string.Format("File Name:{0}\r\n", file_name));

                string description = file_spec.GetDescription();
                if (tab_count > 0)
                    OutputTab(output_txt_doc, tab_count);
                output_txt_doc.Write(string.Format("Description:{0}\r\n", description));
            }
        }

        public static void OutputFolderNodeInfo(TextDoc output_txt_doc, PortfolioFolderNode node, int tab_count) {
            if (tab_count>0)
                OutputTab(output_txt_doc, tab_count);
            output_txt_doc.Write("Type:Folder\r\n");

            string name = node.GetName();
            if (tab_count>0)
                OutputTab(output_txt_doc, tab_count);
            output_txt_doc.Write(string.Format("Name:{0}\r\n", name));

            string description = node.GetDescription();
            if (tab_count>0)
                OutputTab(output_txt_doc, tab_count);
            output_txt_doc.Write(string.Format("Description:{0}\r\n", description));

            using (PortfolioNodeArray sub_nodes = node.GetSortedSubNodes())
            {
                OutputSubNodesInfo(output_txt_doc, sub_nodes, tab_count + 1);
            }
        }

        public static void OutputNodeInfo(TextDoc output_txt_doc, PortfolioNode node, int tab_count) {
            switch (node.GetNodeType()) {
                case PortfolioNode.Type.e_TypeFolder:
                    using (PortfolioFolderNode folder_node = new PortfolioFolderNode(node)) {
                        OutputFolderNodeInfo(output_txt_doc, folder_node, tab_count);
                    }
                    break;
                case PortfolioNode.Type.e_TypeFile:
                    using (PortfolioFileNode file_node = new PortfolioFileNode(node)) {
                        OutputFileNodeInfo(output_txt_doc, file_node, tab_count);
                    }
                    break;
                default:
                    break;
            }
        }

        public static void OutputSubNodesInfo(TextDoc output_txt_doc, PortfolioNodeArray sub_nodes, int tab_count) {
            for (uint index = 0; index<sub_nodes.GetSize(); index++) {
                if (tab_count > 0)
                    OutputTab(output_txt_doc, tab_count);
                output_txt_doc.Write(string.Format("Sorted Index (under current folder):{0}\r\n", index));
                using (PortfolioNode node = sub_nodes.GetAt(index))
                {
                    OutputNodeInfo(output_txt_doc, node, tab_count);
                    output_txt_doc.Write("========\r\n");
                }
            }
        }

        public static void OutputSchemaFields(TextDoc output_txt_doc, SchemaFieldArray field_array) {
            if (field_array.GetSize() <= 0) return;
            output_txt_doc.Write("==== Schema Fields ====\r\n");

            for (uint i = 0; i < field_array.GetSize(); i++) {
                output_txt_doc.Write(string.Format("Field index:{0}\r\n", i));
                using (SchemaField field = field_array.GetAt(i)) {
                    if (true == field.IsEmpty()) continue;
                    string key_name = field.GetKeyName();
                    output_txt_doc.Write(string.Format("Key name: {0}\r\n", key_name));

                    string subtype_name = field.GetSubtypeName();
                    output_txt_doc.Write(string.Format("Subtype name: {0}\r\n", subtype_name));

                    string display_name = field.GetDisplayName();
                    output_txt_doc.Write(string.Format("Display name: {0}\r\n", display_name));

                    bool is_visible = field.IsVisible();
                    output_txt_doc.Write(string.Format("Visibility: {0}\r\n", is_visible ? "true" : "false"));

                    output_txt_doc.Write("========\r\n");
                }
            }
        }

        public static void OutputPortfolioProperties(TextDoc output_txt_doc, Portfolio portfolio) {
            output_txt_doc.Write("==== Portfolio Properties ====\r\n");
            string initial_filespec_keyname = portfolio.GetInitialFileSpecKeyName();
            output_txt_doc.Write(string.Format("Initial FileSpec Key Name:{0}\r\n", initial_filespec_keyname));

            Portfolio.InitialViewMode view_mode = portfolio.GetInitialViewMode();
            string view_mode_str = "";
            switch (view_mode) {
                case Portfolio.InitialViewMode.e_InitialViewUnknownMode:
                    view_mode_str = "Unknown";
                    break;
                case Portfolio.InitialViewMode.e_InitialViewDetailMode:
                    view_mode_str = "Detail";
                    break;
                case Portfolio.InitialViewMode.e_InitialViewTileMode:
                    view_mode_str = "Tile";
                    break;
                case Portfolio.InitialViewMode.e_InitialViewHidden:
                    view_mode_str = "Hidden";
                    break;
            }
            output_txt_doc.Write(string.Format("Initial View Mode:{0}\r\n", view_mode_str));


            bool is_ascending = portfolio.IsSortedInAscending();
            output_txt_doc.Write(string.Format("Sorting Order:{0}\r\n", is_ascending? "Ascending" : "Descending" ));

            string sorting_field_name = portfolio.GetSortingFieldKeyName();
            output_txt_doc.Write(string.Format("Sorting Field Key Name:{0}\r\n", sorting_field_name));

            SchemaFieldArray field_array = portfolio.GetSchemaFields();
            OutputSchemaFields(output_txt_doc, field_array);
        }

        public static void OutputPortfolioPDFInfo(string portfolio_file_path, TextDoc output_txt_doc) {
            using (PDFDoc pdf_doc = new PDFDoc(portfolio_file_path)) {
                ErrorCode error_code = pdf_doc.Load(null);
                if (error_code != ErrorCode.e_ErrSuccess) {
                    Console.WriteLine(string.Format("[FAILED] Fail to load Portfolio PDF file {0}. Error: {1}\n", portfolio_file_path, error_code));
                    return;
                }

                if (false == pdf_doc.IsPortfolio()) {
                    Console.WriteLine(string.Format("[FAILED] Fail to output portfolio information for PDF file {0}, because it is not a portfolio PDF file.", portfolio_file_path));
                    return;
                }

                using (Portfolio exist_portfolio = Portfolio.CreatePortfolio(pdf_doc))
                {
                    if (true == exist_portfolio.IsEmpty())
                    {
                        Console.WriteLine("[FAILED] Fail to create a portfolio object based an existed portfolio PDF document.");
                        return;
                    }

                    // Output portfolio properties.
                    OutputPortfolioProperties(output_txt_doc, exist_portfolio);
                    output_txt_doc.Write("======================================================================\r\n");

                    // Output all nodes.
                    output_txt_doc.Write("==== Nodes Information ====\r\n");
                    using (PortfolioNode root_node = exist_portfolio.GetRootNode())
                    {
                        using (PortfolioFolderNode root_folder = new PortfolioFolderNode(root_node))
                        {
                            using (PortfolioNodeArray sub_nodes = root_folder.GetSortedSubNodes())
                            {
                                OutputSubNodesInfo(output_txt_doc, sub_nodes, 0);
                            }
                        }
                    }
                }
            }
        }

        static void Main(string[] args)
        {
            string output_path = "../output_files/portfolio/";
            System.IO.Directory.CreateDirectory(output_path);

            string sn = "Rew1vB0TqoMIxX444UcpScARWdhgJpsJfzmyMLR32a0+EgrCjp2NaQ==";
            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=";
            // Initialize library
            ErrorCode error_code = Library.Initialize(sn, key);
            if (error_code != ErrorCode.e_ErrSuccess)
            {
                Console.WriteLine("Library Initialize Error: {0}\n", error_code);
                return;
            }

            try
            {
                string saved_portfolio_pdf_path = output_path + "new_portfolio.pdf";
                // Create a new portfolio PDF file
                if (CreatPortfolioPDF(saved_portfolio_pdf_path))
                {
                    string output_info_file_path = output_path + "new_portfolio_info.txt";
                    TextDoc text_doc = new TextDoc(output_info_file_path, FileMode.Create);
                    // Show information of the new portfolio PDF file.
                    OutputPortfolioPDFInfo(saved_portfolio_pdf_path, text_doc);
                }

                Console.WriteLine("END: Portfolio demo.");
            }
            catch (foxit.PDFException e)
            {
                Console.WriteLine(e.Message);
            }

            Library.Release();
        }
    }
}
