/*$
apdtool
Copyright (c) 2020 Azel

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
$*/

/*****************************
 * オプション処理
 *****************************/

#include <stdio.h>
#include <stdlib.h>

#include "mlk.h"
#include "mlk_str.h"
#include "mlk_string.h"
#include "mlk_argparse.h"
#include "mlk_file.h"

#include "def.h"


//---------------

#define VERSION_TEXT "apdtool ver 1.0.1\nCopyright (c) 2020 Azel"

//---------------


/* キーワードの列挙から文字列を検索 */

static int _get_keyword_index(const char *name,const char *keywords,const char *optname)
{
	int no;

	no = mStringGetSplitTextIndex(name, -1, keywords, ';', FALSE);
	if(no == -1)
		puterr_exit("--%s: '%s' is undefined", optname, name);

	return no;
}


//==========================


/* --output */

static void _opt_output(mArgParse *p,char *arg)
{
	mStrSetText_locale(&g_work.strOutput, arg, -1);

	//既存のディレクトリか
	
	if(mStrIsnotEmpty(&g_work.strOutput)
		&& mIsExistDir(g_work.strOutput.buf))
		g_work.flags |= FLAGS_OUTPUT_DIR;
}

/* --format */

static void _opt_format(mArgParse *p,char *arg)
{
	g_work.format = _get_keyword_index(arg, "png;bmp;psd", "format");
}

/* --gray */

static void _opt_gray(mArgParse *p,char *arg)
{
	g_work.flags |= FLAGS_IMAGE_TO_GRAY;
}

/* --mono */

static void _opt_mono(mArgParse *p,char *arg)
{
	g_work.flags |= FLAGS_IMAGE_TO_MONO;
}

/* --layer */

static void _opt_layer(mArgParse *p,char *arg)
{
	g_work.proctype = PROCTYPE_LAYER;
}

/* --layer-prefix */

static void _opt_layer_prefix(mArgParse *p,char *arg)
{
	g_work.flags |= FLAGS_HAVE_LAYER_PREFIX;

	mStrSetText_locale(&g_work.strLayerPrefix, arg, -1);
}

/* --layer-no */

static void _opt_layer_no(mArgParse *p,char *arg)
{
	const char *pc,*end,*p2;
	uint8_t *buf;
	int n1,n2,max;

	if(g_work.layerno_flags) return;

	//値のチェックと最大値を取得

	pc = arg;
	max = -1;

	while(mStringGetNextSplit(&pc, &end, ','))
	{
		for(p2 = pc; p2 < end && *p2 != '-'; p2++);

		if(*p2 == '-' && p2 != pc)
		{
			n1 = atoi(pc);
			n2 = atoi(p2 + 1);
		}
		else
			n1 = n2 = atoi(pc);

		if(n1 < 0 || n2 < 0 || n1 > n2)
			puterr_exit("--layer-no: '%*s' is invalid", end - pc, pc);

		if(n2 > max) max = n2;
	
		pc = end;
	}

	if(max == -1)
		puterr_exit("--layer-no: invalid value");

	//確保

	g_work.layerno_flags = (uint8_t *)mMalloc0((max + 8) >> 3);
	if(!g_work.layerno_flags) return;

	g_work.layerno_num = max + 1;

	//セット

	pc = arg;
	buf = g_work.layerno_flags;

	while(mStringGetNextSplit(&pc, &end, ','))
	{
		for(p2 = pc; p2 < end && *p2 != '-'; p2++);

		if(*p2 != '-')
			n1 = n2 = atoi(pc);
		else
		{
			n1 = atoi(pc);
			n2 = atoi(p2 + 1);
		}

		for(; n1 <= n2; n1++)
			buf[n1 >> 3] |= 1 << (7 - (n1 & 7));
	
		pc = end;
	}
}

/* --layer-no-tex */

static void _opt_layer_no_tex(mArgParse *p,char *arg)
{
	g_work.flags |= FLAGS_LAYER_NO_TEXTURE;
}

/* --info */

static void _opt_info(mArgParse *p,char *arg)
{
	g_work.proctype = PROCTYPE_INFO;
}

/* --texlist */

static void _opt_texlist(mArgParse *p,char *arg)
{
	g_work.proctype = PROCTYPE_INFO;
	g_work.flags |= FLAGS_LAYERTEX_LIST;

	mStrSetText_locale(&g_work.strLayerTex, arg, -1);
}

/* --texcol */

static void _opt_texcol(mArgParse *p,char *arg)
{
	g_work.flags |= FLAGS_LAYERTEX_TO_COL;

	mStrSetText_locale(&g_work.strLayerTex, arg, -1);
}

/* --texpath-sys */

static void _opt_texpath_sys(mArgParse *p,char *arg)
{
	mStrSetText_locale(&g_work.strTexPathSys, arg, -1);
}

/* --texpath-user */

static void _opt_texpath_user(mArgParse *p,char *arg)
{
	mStrSetText_locale(&g_work.strTexPathUser, arg, -1);
}

/* --version */

static void _opt_version(mArgParse *p,char *arg)
{
	puts(VERSION_TEXT);
	exit_app(0);
}

/** ヘルプ表示 */

static void _put_help(const char *exename)
{
	printf("Usage: %s [option] <files...>\n\n", exename);

	puts(
"APD(AzPainter)/ADW(AzDrawing) file tool.\n"
"default is blend image output.\n\n"
"Options:\n"
"  -o,--output=[DIR or NAME]  output directory or filename\n"
"          (default: current directory)\n"
"          <blend output>\n"
"            if filename, determine the format from the extension\n"
"          <layer output> always a directory\n"
"  -i,--info           just display layer information\n"
"  -f,--format=[TYPE]  output image format (blend or layer)\n"
"          png/bmp/psd (default:png)\n"
"  -G,--gray           output blend image to grayscale\n"
"  -M,--mono           output blend image to monochrome\n"
"  -l,--layer          layer output mode\n"
"  -p,--layer-prefix=[PREFIX]\n"
"          for layer output, output file name prefix\n"
"          default: 'INFILENAME_'\n"
"  -n,--layer-no=[n,n1-n2,...]\n"
"          for layer output, index number of layer to output\n"
"  -z,--layer-no-tex\n"
"          for layer output, do not apply layer texture\n"
"  -T,--texlist=[NAME]\n"
"          output path name of layer texture of input file to text file\n"
"          (do not output images)\n"
"  -t,--texcol=[NAME]  for blend or layer output,\n"
"          replace the A16/A1 layer texture with the specified color layer\n"
"          based on the contents described in the text file\n"
"          path@[0-100] : density (%)\n"
"          path#[0-255] : 8bit grayscale color\n"
"  -s,--texpath-sys=[PATH]  system texture path\n"
"  -u,--texpath-user=[PATH] user texture path\n"
"          (default: ~/.azpainter/texture)\n"
"  -V,--version        print program version\n"
"  -h,--help           display this help"
);

	exit_app(0);
}

/* --help */

static void _opt_help(mArgParse *p,char *arg)
{
	_put_help(p->argv[0]);
}


/** 拡張子からフォーマット判別 */

static int _get_output_format(void)
{
	mStr ext = MSTR_INIT;
	int ret = FORMAT_PNG;

	mStrPathGetExt(&ext, g_work.strOutput.buf);

	if(mStrCompareEq_case(&ext, "png"))
		ret = FORMAT_PNG;
	else if(mStrCompareEq_case(&ext, "bmp"))
		ret = FORMAT_BMP;
	else if(mStrCompareEq_case(&ext, "psd"))
		ret = FORMAT_PSD;

	mStrFree(&ext);

	return ret;
}

/** オプション取得
 *
 * return: 通常引数の位置 */

int main_get_options(int argc,char **argv)
{
	mArgParseOpt opts[] = {
		{"output",'o',1,_opt_output},
		{"format",'f',1,_opt_format},
		{"gray",'G',0,_opt_gray},
		{"mono",'M',0,_opt_mono},
		{"layer",'l',0,_opt_layer},
		{"layer-prefix",'p',1,_opt_layer_prefix},
		{"layer-no",'n',1,_opt_layer_no},
		{"layer-no-tex",'z',0,_opt_layer_no_tex},
		{"info",'i',0,_opt_info},
		{"texlist",'T',1,_opt_texlist},
		{"texcol",'t',1,_opt_texcol},
		{"texpath-sys",'s',1,_opt_texpath_sys},
		{"texpath-user",'u',1,_opt_texpath_user},
		{"version",'V',0,_opt_version},
		{"help",'h',0,_opt_help},
		{0,0,0,0}
	};
	mArgParse ap;
	int ind;

	mMemset0(&ap, sizeof(mArgParse));

	ap.argc = argc;
	ap.argv = argv;
	ap.opts = opts;

	ind = mArgParseRun(&ap);

	//解析エラー

	if(ind == -1)
		exit_app(1);

	//入力ファイルがない

	if(ind == 0)
		_put_help(argv[0]);

	//合成画像出力で、--output が既存ディレクトリでない (ファイル指定) の場合、
	//拡張子からフォーマット判別

	if(g_work.proctype == PROCTYPE_BLEND
		&& mStrIsnotEmpty(&g_work.strOutput)
		&& !(g_work.flags & FLAGS_OUTPUT_DIR))
	{
		g_work.format = _get_output_format();
	}

	return ind;
}
