/*フレームフックの相手をするため専用*/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <SDL/SDL.h>
#include "common/framehook_ext.h"
#include "framehook.h"
#include "main.h"
#include "mydef.h"
#include "nicodef.h"
#include "util.h"

typedef struct ContextInfo{
	FILE* log;
	DATA data;
} ContextInfo;

/*
 * 必要な関数ひとつめ。最初に呼ばれるよ！
 * 
 */
int init_setting(FILE*log,const toolbox *tbox,SETTING* setting,int argc, char *argv[]);

__declspec(dllexport) int ExtConfigure(void **ctxp,const toolbox *tbox, int argc, char *argv[]){
	int i;
	//ログ
	FILE* log = fopen("[log]vhext.txt", "w");
	if(log == NULL){
		puts("[framehook/init]failed to open logfile.\n");
		fflush(log);
		return -1;
	}else{
		fputs("[framehook/init]initializing..\n",log);
		fflush(log);
	}
	//必要な設定があるかの確認
	fprintf(log,"[framehook/init]called with argc = %d\n",argc);
	fflush(log);
	for(i=0;i<argc;i++){
		fprintf(log,"[framehook/init]arg[%2d] = %s\n",i,argv[i]);
		fflush(log);
	}
	//セッティング取得。
	SETTING setting;
	if(init_setting(log,tbox,&setting,argc,argv)){
		fputs("[framehook/init]initialized settings.\n",log);
		fflush(log);
	}else{
		fputs("[framehook/init]failed to initialize settings.\n",log);
		fflush(log);
		return -2;
	}
	//ライブラリなどの初期化
	if(init(log)){
		fputs("[framehook/init]initialized libs.\n",log);
		fflush(log);
	}else{
		fputs("[framehook/init]failed to initialize libs.\n",log);
		fflush(log);
		return -3;
	}
	/*コンテキストの設定*/
	*ctxp = malloc(sizeof(ContextInfo));
	if(*ctxp == NULL){
		fputs("[framehook/init]initialized to malloc for context.\n",log);
		fflush(log);
	}
	ContextInfo* ci = (ContextInfo*)*ctxp;
	ci->log = log;
	fflush(log);
	if(initData(&ci->data,log,&setting)){
		fputs("[framehook/init]initialized context.\n",log);
		fputs("[framehook/init]initialized.\n",log);
		fflush(log);
		return 0;
	}else{
		fputs("[framehook/init]failed to initialize context.\n",log);
		fflush(log);
		return -4;
	}
}
/*
 * 内部でのみ呼ばれる。
 */

 /*
	argv[0]:プログラム
	argv[1]:vhook
	argv[2]:フォント
	argv[3]:フォントインデックス
	argv[4]:一画面
	argv[5]:影の種類
	以降オプション
	--enable-show-video：描画中に動画を見せる。
	--enable-fontsize-fix：フォントサイズを自動で調整する。
*/
 
int init_setting(FILE*log,const toolbox *tbox,SETTING* setting,int argc, char *argv[]){
	/*videoの長さ*/
	setting->video_length = (tbox->video_length * VPOS_FACTOR);
	/*以降オプション*/
	
	//コメントを見せるか否か？
	setting->enable_user_comment = FALSE;
	setting->enable_owner_comment = FALSE;
	setting->data_user_path = NULL;
	setting->data_owner_path = NULL;
	//一般的な設定
	setting->font_path = NULL;
	setting->font_index = 0;
	setting->user_slot_max = 30;
	setting->owner_slot_max = 30;
	setting->shadow_kind = 1;//デフォルトはニコニコ動画風
	setting->show_video = FALSE;
	setting->fontsize_fix=FALSE;
	setting->opaque_comment=FALSE;
	int i;
	char* arg;
	for(i=0;i<argc;i++){
		arg = argv[i];
		if(!setting->data_user_path && strncmp(FRAMEHOOK_OPT_DATA_USER,arg,FRAMEHOOK_OPT_DATA_USER_LEN) == 0){
			char* data_user = arg+FRAMEHOOK_OPT_DATA_USER_LEN;
			setting->data_user_path = data_user;
			setting->enable_user_comment = TRUE;
			fprintf(log,"[framehook/init]User Comment data path:%s\n",setting->data_user_path);
			fflush(log);
		}else if(!setting->data_owner_path && strncmp(FRAMEHOOK_OPT_DATA_OWNER,arg,FRAMEHOOK_OPT_DATA_OWNER_LEN) == 0){
			char* data_owner = arg+FRAMEHOOK_OPT_DATA_OWNER_LEN;
			setting->data_owner_path = data_owner;
			setting->enable_owner_comment = TRUE;
			fprintf(log,"[framehook/init]Owner Comment data path:%s\n",setting->data_owner_path);
			fflush(log);
		}else if(!setting->font_path && strncmp(FRAMEHOOK_OPT_FONT,arg,FRAMEHOOK_OPT_FONT_LEN) == 0){
			char* font = arg+FRAMEHOOK_OPT_FONT_LEN;
			setting->font_path = font;
			fprintf(log,"[framehook/init]Font path:%s\n",setting->font_path);
			fflush(log);
		}else if(strncmp(FRAMEHOOK_OPT_FONTINDEX,arg,FRAMEHOOK_OPT_FONTINDEX_LEN) == 0){
			setting->font_index = MAX(0,atoi(arg+FRAMEHOOK_OPT_FONTINDEX_LEN));
			fprintf(log,"[framehook/init]font index:%d\n",setting->font_index);
			fflush(log);
		}else if(strncmp(FRAMEHOOK_OPT_SHADOW,arg,FRAMEHOOK_OPT_SHADOW_LEN) == 0){
			setting->shadow_kind = MAX(0,atoi(arg+FRAMEHOOK_OPT_SHADOW_LEN));
			fprintf(log,"[framehook/init]shadow kind:%d\n",setting->shadow_kind);
			fflush(log);
		}else if(strncmp(FRAMEHOOK_OPT_SHOW_USER,arg,FRAMEHOOK_OPT_SHOW_USER_LEN) == 0){
			setting->user_slot_max = MAX(0,atoi(arg+FRAMEHOOK_OPT_SHOW_USER_LEN));
			fprintf(log,"[framehook/init]User Comments on screen:%d\n",setting->user_slot_max);
			fflush(log);
		}else if(strncmp(FRAMEHOOK_OPT_SHOW_OWNER,arg,FRAMEHOOK_OPT_SHOW_OWNER_LEN) == 0){
			setting->owner_slot_max = MAX(0,atoi(arg+FRAMEHOOK_OPT_SHOW_OWNER_LEN));
			fprintf(log,"[framehook/init]Owner Comments on screen:%d\n",setting->owner_slot_max);
			fflush(log);
		}else if(!setting->show_video && strcmp(arg,"--enable-show-video") == 0){
			fputs("[framehook/init]show video while converting.\n",log);
			fflush(log);
			setting->show_video=TRUE;
		}else if(!setting->fontsize_fix && strcmp(arg,"--enable-fix-font-size") == 0){
			fputs("[framehook/init]fix font size automatically.\n",log);
			fflush(log);
			setting->fontsize_fix=TRUE;
		}else if(!setting->opaque_comment && strcmp(arg,"--enable-opaque-comment") == 0){
			fputs("[framehook/init]enable opaque comment.\n",log);
			fflush(log);
			setting->opaque_comment=TRUE;
		}
	}
	//引数を正しく入力したか否かのチェック
	//ここでチェックしているの以外は、デフォルト設定で逃げる。
	if(!setting->font_path){
		fputs("[framehook/init]please set FONT PATH.\n",log);
		fflush(log);
		return FALSE;
	}
	return TRUE;
}

/*
 * 必要な関数二つめ。フレームごとに呼ばれるよ！
 * 
 */
__declspec(dllexport) void ExtProcess(void *ctx,const toolbox *tbox,vhext_frame *pict){
    ContextInfo *ci = (ContextInfo *) ctx;
    FILE* log = ci->log;

	/* Note:
	 * Saccubus 1.22以降の拡張vhookフィルタでは、RGB24フォーマットでのみ
	 * 画像が提供されます。
	 */

  	//SDLのサーフェイスに変換
    SDL_Surface* surf = SDL_CreateRGBSurfaceFrom(pict->data,
    											pict->w,pict->h,24,pict->linesize,
												#if SDL_BYTEORDER == SDL_BIG_ENDIAN
												    0xff000000,
												    0x00ff0000,
												    0x0000ff00,
												#else
												    0x000000ff,
												    0x0000ff00,
												    0x00ff0000,
												#endif
												    0x00000000
												);
	//フィルタ
	int now_vpos = (pict->pts * VPOS_FACTOR);
	if(!main_process(&ci->data,surf,now_vpos)){
		fputs("[framehook/process]failed to process.\n",log);
		fflush(log);
		exit(1);
	}
	//サーフェイス開放
	SDL_FreeSurface(surf);
	fflush(log);
}

/*
 * 必要な関数最後。終わったら呼ばれるよ！
 * 
 */

__declspec(dllexport) void ExtRelease(void *ctx,const toolbox *tbox){
    ContextInfo *ci;
    ci = (ContextInfo *) ctx;
    FILE* log = ci->log;
    fputs("[framehook/close]closing...\n",log);
    if (ctx) {
        closeData(&ci->data);
	    fputs("[framehook/close]closed.\n",log);
        fclose(log);
	    //コンテキスト全体
        free(ctx);
    }
    //ライブラリの終了
    close();
}

