/*
	Antenna House PDF Tool API V8.0
	C++ Interface sample program

	概要：しおり情報の取得

	Copyright 2013-2025 Antenna House, Inc.
*/

#include < PdfTk.h >
#include < stdio.h >

using namespace PdfTk;

void readOutline(PtlOutline& item, int indent, bool showDetail);
void showAction(PtlAction& action);
void showDest(PtlDest& dest);

int main(int argc, char* argv[])
{
	if (argc < 3) {
		printf("usage: GetOutline.exe in-pdf-file 取得方法\n\n");
		printf("取得方法\n0 : しおりのツリー　1 : しおりの詳細\n");
		return 1;
	}
	try
	{
		PtlParamInput input(argv[1]);

		bool showDetail = false;
		const char* kind = argv[2];
		switch (kind[0]) {
		case '0':
			break;
		case '1':
			showDetail = true;
			break;
		default:
			printf("usage: GetOutline.exe in-pdf-file 取得方法\n\n");
			printf("取得方法\n0 : しおりのツリー　1 : しおりの詳細\n");
			return 1;
		}

		PtlPDFDocument doc;

		// PDFファイルをロードします。
		doc.load(input);

		if (!doc.hasOutlines()){
			printf("アウトラインを持っていない！\n");
			return 0;
		}

		// ルートアウトラインの取得
		PtlOutline rootOutline = doc.getRootOutline();

		if (rootOutline.hasChild()) {
			PtlOutline outline = rootOutline.getFirstChild();
            readOutline(outline, 0, showDetail);
		}

		printf("完了!\n");
	}
	catch (const PtlException &e)
	{
		fprintf(stderr, "Error code : %d\n %s\n", e.getErrorCode(), e.getErrorMessage().c_str());
		return 1;
	}	
	return 0;
}

void readOutline(PtlOutline& item, int indent, bool showDetail)
{
	PtlParamString title = item.getTitle();
	if (showDetail) {
		printf("Title = %s\n", title.c_str());
		printf("Indent = %d\n", indent);
		if (item.isOpen())
		{
			printf("子アウトラインをオープンする\n");
		}
		else
		{
			printf("子アウトラインをオープンしない\n");
		}
		int flags = item.getFlags();
		if ((flags & PtlOutline::FLAG_BOLD) == PtlOutline::FLAG_BOLD)
			printf("FLAG_BOLD on\n" );
		else
			printf("FLAG_BOLD off\n" );
		if ((flags & PtlOutline::FLAG_ITALIC) == PtlOutline::FLAG_ITALIC)
			printf("FLAG_ITALIC on\n" );
		else
			printf("FLAG_ITALIC off\n" );
		PtlColorDeviceRGB color = item.getColor();
		int rr = (int)(color.getR() * 255);
		int gg = (int)(color.getG() * 255);
		int bb = (int)(color.getB() * 255);
		printf("Color = RGB(%d,%d,%d)\n", rr, gg, bb);
		PtlAction act = item.getAction();
		showAction(act);
	} else {
		std::string indentString = "";
		for(int i=0; i < indent; ++i) {
			indentString += "  ";
		}
		if (showDetail == false) {
			printf(indentString.c_str());
		}
		printf(title.c_str());
		printf("\n");
	}

	if (item.hasChild()) {
		PtlOutline firstItem = item.getFirstChild();
		int indentChild = indent;
		indentChild++;
		readOutline(firstItem, indentChild, showDetail);
	}
	if (item.hasNextSibling()) {
		PtlOutline nextItem = item.getNextSibling();
		readOutline(nextItem, indent, showDetail);
	}
}

void showAction(PtlAction& action)
{
	switch (action.getType()){
	case PtlAction::TYPE_NONE:{
		printf("Action : %d : アクションなし\n", PtlAction::TYPE_NONE);
		break;}
	case PtlAction::TYPE_GOTO:{
		printf("Action : %d : GoToアクション\n", PtlAction::TYPE_GOTO);
		PtlActionGoTo act = (PtlActionGoTo&)action;
		// 宛先の取得
		showDest(act.getDest());
		break;}
	case PtlAction::TYPE_GOTO_R:{
		printf("Action : %d : GoToRアクション\n", PtlAction::TYPE_GOTO_R);
		PtlActionGoToR act = (PtlActionGoToR&)action;
		// ファイル間移動用PDFファイル名を取得 getFileName()
		printf("FileName : %s\n", act.getFileName().c_str());
		// 新ウィンドウフラグを取得
		if (act.getNewWindowFlag()){
			printf("NewWindowFlag : true: 新ウィンドウでオープンする\n");
		}else{
			printf("NewWindowFlag : false: しない\n");
		}
		// 宛先の取得
		showDest(act.getDest());
		break;}
	case PtlAction::TYPE_LAUNCH:{
		printf("Action : %d : Launchアクション\n", PtlAction::TYPE_LAUNCH);
		PtlActionLaunch act = (PtlActionLaunch&)action;
		// 起動ファイル名を取得
		printf("FileName : %s\n", act.getFileName().c_str());
		// 新ウィンドウフラグを取得
		if (act.getNewWindowFlag()){
			printf("NewWindowFlag : true: 新ウィンドウでオープンする\n");
		}else{
			printf("NewWindowFlag : false: しない\n");
		}
		break;}
	case PtlAction::TYPE_URI:{
		printf("Action : %d : URIアクション\n", PtlAction::TYPE_URI);
		PtlActionURI act = (PtlActionURI&)action;
		// URIを取得
		printf("URI : %s\n", act.getURI().c_str());
		break;}
	case PtlAction::TYPE_UNKNOWN:{
		printf("Action : %d : 未対応アクション\n", PtlAction::TYPE_UNKNOWN);
		break;}
	}
}

void showDest(PtlDest& dest)
{
	switch (dest.getType()){
	case PtlDest::TYPE_NONE:
		printf("Dest : %d : 宛先なし\n", PtlDest::TYPE_NONE);
		break;
	case PtlDest::TYPE_XYZ:
		printf("Dest : %d : XYZ型\n", PtlDest::TYPE_XYZ);
		break;
	case PtlDest::TYPE_FIT:
		printf("Dest : %d : Fit型(全体)\n", PtlDest::TYPE_FIT);
		break;
	case PtlDest::TYPE_FIT_H:
		printf("Dest : %d : FitH型(幅に合わせる)\n", PtlDest::TYPE_FIT_H);
		break;
	case PtlDest::TYPE_FIT_V:
		printf("Dest : %d : FitV型(高さに合わせる)\n", PtlDest::TYPE_FIT_V);
		break;
	case PtlDest::TYPE_FIT_R:
		printf("Dest : %d : FitR型\n", PtlDest::TYPE_FIT_R);
		break;
	case PtlDest::TYPE_FIT_B:
		printf("Dest : %d : FitB型\n", PtlDest::TYPE_FIT_B);
		break;
	case PtlDest::TYPE_FIT_BH:
		printf("Dest : %d : FitBH型(描画領域の幅に合わせる)\n", PtlDest::TYPE_FIT_BH);
		break;
	case PtlDest::TYPE_FIT_BV:
		printf("Dest : %d : FitBV型\n", PtlDest::TYPE_FIT_BV);
		break;
	}
	// 宛先ページの取得
	printf("宛先ページ(PageNumber) : %d ページ目\n", dest.getPageNumber());
}

