/**********************************************************************
 
	Copyright (C) 2003 Hirohisa MORI <joshua@nichibun.ac.jp>
 
	This program is free software; you can redistribute it 
	and/or modify it under the terms of the GLOBALBASE 
	Library General Public License (G-LGPL) as published by 

	http://www.globalbase.org/
 
	This program is distributed in the hope that it will be 
	useful, but WITHOUT ANY WARRANTY; without even the 
	implied warranty of MERCHANTABILITY or FITNESS FOR A 
	PARTICULAR PURPOSE.

**********************************************************************/

#include "attr_data.h"
#include <string.h>

#define TAB "\t"

#define PG_SI_TYO					0
#define PG_OHAZA					1
#define PG_GAIKU					2
#define PG_ROAD						3
#define PG_TETUDOU					4
#define PG_EKI						5
#define PG_KOUEN					6
#define PG_GAKKOU					7
#define PG_JINJYA					8
#define PG_BOTI						9
#define PG_SONOTA					10
#define PG_KASEN					11
#define PG_MIZUUMI					12
#define PG_TATEMONO					13
#define PG_SANKAKU_TEN				14
#define PG_SYADOU_HODOU_KYOUKAISEN	15
#define PG_DOURO_KUIKI_KYOUKAISEN	16
#define PG_KASEN_KUIKI				17
#define PG_KASEN_CENTER				18

/*"市区町村"*/
/*
char *g_display_names_of_code[] = {"市区町村","大字町丁目","街区","道路線","鉄道","駅","都市公園",
									"学校敷地","神社寺院境内","墓地","場地","河川","湖池等","公共建物",
									"三角点","車道歩道の境界線","道路の区域境界線","河川の区域","河川中心線"};
*/
/*
char *g_attr_names[19][11][] = {
	{"都道府県コード","市区町村名","","","","","","","","",""},
	{"都道府県コード","町丁目コード","大字町丁名","","","","","","","",""},
	{"都道府県コード","町丁目コード","大字町丁名","市街区符号等","","","","","","",""},
	{"名称","別称","","","","","","","","",""},
	{"路線名","","","","","","","","","",""},
	{"名称","","","","","","","","","",""},
	{"名称","","","","","","","","","",""},
	{"名称","","","","","","","","","",""},// 学校敷地
	{"名称","","","","","","","","","",""},// 神社・境内
	{"名称","","","","","","","","","",""},// 墓地
	{"名称","","","","","","","","","",""},// その他場地
	{"名称","","","","","","","","","",""},// 河川
	{"名称","","","","","","","","","",""},// 湖池等
	{"公共建物コード","名称","","","","","","","","",""},// 公共建物
	{"３次メッシュ","点コード","点名","地図コード","緯度","経度","等級の種別","座標系","平面直角座標のＸ","平面直角座標のＹ","標高"},// 三角点
	{"個別番号","中心線位置","","","","","","","","",""},// 車道・歩道の境界線
	{"個別番号","中心線位置","","","","","","","","",""},// 道路の区域の境界線
	{"名称","個別番号","中心線位置","","","","","","","",""},// 河川の区域
	{"名称","","","","","","","","","",""} // 河川中心線
};
*/

/* disable waring "converted int to char" for VisualC++ */
#pragma warning(disable: 4305)

char g_display_names_of_code[][32] = {
	{0x8e,0x73,0x8b,0xe6,0x92,0xac,0x91,0xba,0x00},
	{0x91,0xe5,0x8e,0x9a,0x92,0xac,0x92,0x9a,0x96,0xda,0x00},
	{0x8a,0x58,0x8b,0xe6,0x00},
	{0x93,0xb9,0x98,0x48,0x90,0xfc,0x00},
	{0x93,0x53,0x93,0xb9,0x00},
	{0x89,0x77,0x00},
	{0x93,0x73,0x8e,0x73,0x8c,0xf6,0x89,0x80,0x00},
	{0x8a,0x77,0x8d,0x5a,0x95,0x7e,0x92,0x6e,0x00},
	{0x90,0x5f,0x8e,0xd0,0x8e,0x9b,0x89,0x40,0x8b,0xab,0x93,0xe0,0x00},
	{0x95,0xe6,0x92,0x6e,0x00},
	{0x8f,0xea,0x92,0x6e,0x00},
	{0x89,0xcd,0x90,0xec,0x00},
	{0x8c,0xce,0x92,0x72,0x93,0x99,0x00},
	{0x8c,0xf6,0x8b,0xa4,0x8c,0x9a,0x95,0xa8,0x00},
	{0x8e,0x4f,0x8a,0x70,0x93,0x5f,0x00},
	{0x8e,0xd4,0x93,0xb9,0x95,0xe0,0x93,0xb9,0x82,0xcc,0x8b,0xab,0x8a,0x45,0x90,0xfc,0x00},
	{0x93,0xb9,0x98,0x48,0x82,0xcc,0x8b,0xe6,0x88,0xe6,0x8b,0xab,0x8a,0x45,0x90,0xfc,0x00},
	{0x89,0xcd,0x90,0xec,0x82,0xcc,0x8b,0xe6,0x88,0xe6,0x00},
	{0x89,0xcd,0x90,0xec,0x92,0x86,0x90,0x53,0x90,0xfc,0x00}
};

char g_attr_names[19][11][32] = {
	{
		{0x43,0x6c,0x69,0x70,0x62,0x6f,0x61,0x72,0x64,0x00},
		{0x8e,0x73,0x8b,0xe6,0x92,0xac,0x91,0xba,0x96,0xbc,0x00},
		"","","","","","","","",""
	},
	{
		{0x93,0x73,0x93,0xb9,0x95,0x7b,0x8c,0xa7,0x83,0x52,0x81,0x5b,0x83,0x68,0x00},
		{0x92,0xac,0x92,0x9a,0x96,0xda,0x83,0x52,0x81,0x5b,0x83,0x68,0x00},
		{0x91,0xe5,0x8e,0x9a,0x92,0xac,0x92,0x9a,0x96,0xbc,0x00},
		"","","","","","","",""
	},
	{
		{0x93,0x73,0x93,0xb9,0x95,0x7b,0x8c,0xa7,0x83,0x52,0x81,0x5b,0x83,0x68,0x00},
		{0x92,0xac,0x92,0x9a,0x96,0xda,0x83,0x52,0x81,0x5b,0x83,0x68,0x00},
		{0x91,0xe5,0x8e,0x9a,0x92,0xac,0x92,0x9a,0x96,0xbc,0x00},
		{0x8e,0x73,0x8a,0x58,0x8b,0xe6,0x95,0x84,0x8d,0x86,0x93,0x99,0x00},
		"","","","","","",""
	},
	{
		{0x96,0xbc,0x8f,0xcc,0x00},
		{0x95,0xca,0x8f,0xcc,0x00},
		"","","","","","","","",""
	},
	{
		{0x98,0x48,0x90,0xfc,0x96,0xbc,0x00},
		"","","","","","","","","",""
	},
	{
		{0x96,0xbc,0x8f,0xcc,0x00},
		"","","","","","","","","",""
	},
	{
		{0x96,0xbc,0x8f,0xcc,0x00},
		"","","","","","","","","",""
	},
	{
		{0x96,0xbc,0x8f,0xcc,0x00},
		"","","","","","","","","",""
	},
	{
		{0x96,0xbc,0x8f,0xcc,0x00},
		"","","","","","","","","",""
	},
	{
		{0x96,0xbc,0x8f,0xcc,0x00},
		"","","","","","","","","",""
	},
	{
		{0x96,0xbc,0x8f,0xcc,0x00},
		"","","","","","","","","",""
	},
	{
		{0x96,0xbc,0x8f,0xcc,0x00},
		"","","","","","","","","",""
	},
	{
		{0x96,0xbc,0x8f,0xcc,0x00},
		"","","","","","","","","",""
	},
	{
		{0x8c,0xf6,0x8b,0xa4,0x8c,0x9a,0x95,0xa8,0x83,0x52,0x81,0x5b,0x83,0x68,0x00},
		{0x96,0xbc,0x8f,0xcc,0x00},
		"","","","","","","","",""
	},
	{
		{0x82,0x52,0x8e,0x9f,0x83,0x81,0x83,0x62,0x83,0x56,0x83,0x85,0x00},
		{0x93,0x5f,0x83,0x52,0x81,0x5b,0x83,0x68,0x00},
		{0x93,0x5f,0x96,0xbc,0x00},
		{0x92,0x6e,0x90,0x7d,0x83,0x52,0x81,0x5b,0x83,0x68,0x00},
		{0x88,0xdc,0x93,0x78,0x00},
		{0x8c,0x6f,0x93,0x78,0x00},
		{0x93,0x99,0x8b,0x89,0x82,0xcc,0x8e,0xed,0x95,0xca,0x00},
		{0x8d,0xc0,0x95,0x57,0x8c,0x6e,0x00},
		{0x95,0xbd,0x96,0xca,0x92,0xbc,0x8a,0x70,0x8d,0xc0,0x95,0x57,0x82,0xcc,0x82,0x77,0x00},
		{0x95,0xbd,0x96,0xca,0x92,0xbc,0x8a,0x70,0x8d,0xc0,0x95,0x57,0x82,0xcc,0x82,0x78,0x00},
		{0x95,0x57,0x8d,0x82,0x00}
	},
	{
		{0x8c,0xc2,0x95,0xca,0x94,0xd4,0x8d,0x86,0x00},
		{0x92,0x86,0x90,0x53,0x90,0xfc,0x88,0xca,0x92,0x75,0x00},
		"","","","","","","","",""
	},
	{
		{0x8c,0xc2,0x95,0xca,0x94,0xd4,0x8d,0x86,0x00},
		{0x92,0x86,0x90,0x53,0x90,0xfc,0x88,0xca,0x92,0x75,0x00},
		"","","","","","","","",""
	},
	{
		{0x96,0xbc,0x8f,0xcc,0x00},
		{0x8c,0xc2,0x95,0xca,0x94,0xd4,0x8d,0x86,0x00},
		{0x92,0x86,0x90,0x53,0x90,0xfc,0x88,0xca,0x92,0x75,0x00},
		"","","","","","","",""
	},
	{
		{0x96,0xbc,0x8f,0xcc,0x00},
		"","","","","","","","","",""
	}
};


//ポリゴンファイルから読み込み
int ReadAttr(const char *filename, FILE *fp, ATTR_DATA *pData){
	char szBuff[256];
	KIBAN_FILE_HEADER *pHeader=&(pData->header);
	int nReturn;
	ATTR_RECORD *pRecord;
	int i;
	
	//ヘッダの切り出し
	char seps[]  = " ,\t\n";
	char *token;
	
	//ヘッダ読み込み
	if(!(nReturn = ReadKibanFileHeader(fp, pHeader))==ID_ERR_NOERROR){
		printf("::header error at %s\n", filename);
		return nReturn;
	}
	
	//属性レコード読み込み
	pData->record = (ATTR_RECORD *)malloc(pHeader->record_count*sizeof(ATTR_RECORD));
	pRecord = pData->record ;
	
	for(i=0;i<pHeader->record_count;){
		int j;
		if(!fgets(szBuff,sizeof(szBuff),fp)){
			pHeader->record_count=i;
			printf("::record count error at %s\n", pData->header.file_name);
			return ID_ERR_NOERROR;
			/*return ID_ERR_FILE_FORMAT;*/
		}
		chop(szBuff);
		
		//書式分類レコード
		token = strtok( szBuff, seps );
		if(token==NULL){
			printf("::record format error at %s\n", pData->header.file_name);
			continue;
		}

		strcpy(pRecord->code,token);
		
		//個別番号：9
		token = strtok( NULL, seps );
		if(token==NULL){
			printf("::record format error at %s\n", pData->header.file_name);
			continue;
		}
		pRecord->id = atoi(token);
		
		//属性数：24
		token = strtok( NULL, seps );
		if(token==NULL){
			printf("::record format error at %s\n", pData->header.file_name);
			continue;
		}
		pRecord->attr_count = atoi(token);
		if(pRecord->attr_count>20){
			pRecord->attr_count=0;
		}

		//各座標情報の読み込み
		for(j=0;j<pRecord->attr_count;++j){
			int pos;
			//属性の取得
			token = strtok( NULL, seps );
			if(token==NULL){
				//属性が設定されていない(attr_count分の設定されていない)なら、空文字を設定して抜ける
				for(;j<pRecord->attr_count;++j){
					pRecord->pszAttrs[j] = (char *)malloc(1);
					pRecord->pszAttrs[j][0] = '\0';
				}
				break;
			}
			pos = strlen(token)+1;
			pRecord->pszAttrs[j] = (char *)malloc(pos);
			strcpy(pRecord->pszAttrs[j],token);
			
			//属性は、空っぽの場合",,"となるので、カンマが続いているなら、pszAttrsに空白をセット
			while(token[pos] == ','){
				++pos;++j;
				pRecord->pszAttrs[j] = (char *)malloc(1);
				pRecord->pszAttrs[j][0] = '\0';
			}
		}
		++pRecord;
		++i;
	}
	return ID_ERR_NOERROR;
}

int GetPolygonIntCode(const char *szCodeFrom){
	char szCode[6];
    memset(szCode,0,sizeof(szCode));
    strncpy(szCode, szCodeFrom,5);
	/* si_tyo */
	if(!strcmp(szCode,"A1105")){return PG_SI_TYO;}
    /* ohaza,tyoutyoumei */
	if(!strcmp(szCode,"A1106")){return PG_OHAZA;}
    /* gaiku */
	if(!strcmp(szCode,"A1108")){return PG_GAIKU;}
    /* douro */
	if(!strcmp(szCode,"L2110")){return PG_ROAD;}
    /* tetudou */
	if(!strcmp(szCode,"L2300")){return PG_TETUDOU;}
    /* eki */
	if(!strcmp(szCode,"L2420")){return PG_EKI;}
    /* tosi_kouen */
	if(!strcmp(szCode,"A6242")){return PG_KOUEN;}
    /* gakkou */
	if(!strcmp(szCode,"A6243")){return PG_GAKKOU;}
    /* jinjya */
	if(!strcmp(szCode,"A6244")){return PG_JINJYA;}
    /* boti */
	if(!strcmp(szCode,"A6215")){return PG_BOTI;}
    /* sonota no jyouti */
	if(!strcmp(szCode,"A6200")){return PG_SONOTA;}
    /* kasen */
	if(!strcmp(szCode,"A5101")){return PG_KASEN;}
    /* mizuumi */
	if(!strcmp(szCode,"A5105")){return PG_MIZUUMI;}
    /* koukyou_tatemono */
	if(!strcmp(szCode,"A3500")){return PG_TATEMONO;}
    /* sannkaku_ten */
	if(!strcmp(szCode,"P7301")){return PG_SANKAKU_TEN;}
    /* syadou_hodou_no_kyoukaisen */
	if(!strcmp(szCode,"L2112")){return PG_SYADOU_HODOU_KYOUKAISEN;}
    /* douro_no_kuiki_no_kyoukaisen */
	if(!strcmp(szCode,"L2101")){return PG_DOURO_KUIKI_KYOUKAISEN;}
    /* kasen_no_kuiki */
	if(!strcmp(szCode,"A5121")){return PG_KASEN_KUIKI;}
    /* kasen_cyuusin_sen */
	if(!strcmp(szCode,"L5122")){return PG_KASEN_CENTER;}
	return 0;
}

int Attr2XML(FILE *fp, ATTR_DATA *pAttr){
	ATTR_RECORD *pAttrRecord = pAttr->record;
	int i;
	for(i=0;i<pAttr->header.record_count; ++i,++pAttrRecord){
		AttrRecord2XML(fp, pAttrRecord);
	}
	return ID_ERR_NOERROR;
}

void PrintXMLSubInformation(FILE *fp, int nCode, ATTR_RECORD *pAttrRecord){
	int i;
	char *attr0,*attr1,*attr2;
	if(pAttrRecord->attr_count>=1)
		attr0 = pAttrRecord->pszAttrs[0];
	else
		attr0 = "";
	if(pAttrRecord->attr_count>=2)
		attr1 = pAttrRecord->pszAttrs[1];
	else
		attr1 = "";
	
	if(pAttrRecord->attr_count>=3)
		attr2 = pAttrRecord->pszAttrs[2];
	else
		attr2 = "";

	switch(nCode){
		case PG_SI_TYO:
			fprintf(fp,TAB"<%s scheme=\"JIS\">%s</%s>\n", 
				g_attr_names[nCode][0], attr0, g_attr_names[nCode][0]);
			fprintf(fp,TAB"<%s>%s</%s>\n", 
				g_attr_names[nCode][1], attr1, g_attr_names[nCode][1]);
		break;
		case PG_OHAZA:
			fprintf(fp,TAB"<%s scheme=\"JIS\">%s</%s>\n", 
				g_attr_names[nCode][0], attr0, g_attr_names[nCode][0]);
			fprintf(fp,TAB"<%s>%s</%s>\n",
				g_attr_names[nCode][1], attr1, g_attr_names[nCode][1]);
			fprintf(fp,TAB"<%s>%s</%s>\n", 
				g_attr_names[nCode][2], attr2, g_attr_names[nCode][2]);
		break;
		case PG_GAIKU:
			{
				fprintf(fp,TAB"<%s scheme=\"JIS\">%s</%s>\n", 
					g_attr_names[nCode][0], attr0, g_attr_names[nCode][0]);
				fprintf(fp,TAB"<%s>%s</%s>\n",
					g_attr_names[nCode][1], attr1, g_attr_names[nCode][1]);
				fprintf(fp,TAB"<%s>%s</%s>\n", 
					g_attr_names[nCode][2], attr2, g_attr_names[nCode][2]);
				for(i = 3; i<pAttrRecord->attr_count ; ++i){
					fprintf(fp, TAB"<%s>%s</%s>\n",
						g_attr_names[nCode][3], pAttrRecord->pszAttrs[i], g_attr_names[nCode][3]);
				}
			}
		break;
		case PG_ROAD:
			{
				fprintf(fp,TAB"<%s>%s</%s>\n",
					g_attr_names[nCode][0], attr0, g_attr_names[nCode][0]);
				for(i = 1; i<pAttrRecord->attr_count ; ++i){
					fprintf(fp,TAB"<%s>%s</%s>\n",
						g_attr_names[nCode][1], pAttrRecord->pszAttrs[i], g_attr_names[nCode][1]);
				}
			}
		break;
		case PG_TETUDOU:
		case PG_EKI:
		case PG_KOUEN:
		case PG_GAKKOU:
		case PG_JINJYA:
		case PG_BOTI:
		case PG_SONOTA:
		case PG_KASEN:
		case PG_MIZUUMI:
			fprintf(fp,TAB"<%s>%s</%s>\n", 
				g_attr_names[nCode][0], attr0, g_attr_names[nCode][0]);
		break;
		case PG_TATEMONO:
			{
				for(i = 0; i<pAttrRecord->attr_count ; ++i){
					fprintf(fp, TAB"<Element>\n");
					fprintf(fp, TAB TAB "<%s>%s</%s>\n", g_attr_names[nCode][0], pAttrRecord->pszAttrs[i], g_attr_names[nCode][0]);
					if(i+1 < pAttrRecord->attr_count)
						fprintf(fp, TAB TAB "<%s>%s</%s>\n", g_attr_names[nCode][1], pAttrRecord->pszAttrs[++i], g_attr_names[nCode][1]);
					fprintf(fp, TAB"</Element>\n");
				}
			}
		break;
		case PG_SANKAKU_TEN:
		case PG_SYADOU_HODOU_KYOUKAISEN:
		case PG_DOURO_KUIKI_KYOUKAISEN:
		case PG_KASEN_KUIKI:
		case PG_KASEN_CENTER:
			{
				for(i=0; i<pAttrRecord->attr_count ; ++i){
					fprintf(fp,TAB"<%s>%s</%s>\n", 
						g_attr_names[nCode][i], pAttrRecord->pszAttrs[i], g_attr_names[nCode][i]);
				}
			}
		break;
	}
}
	
int AttrRecord2XML(FILE *fp, ATTR_RECORD *pAttrRecord){
	int nCode = GetPolygonIntCode(pAttrRecord->code);
	int j=0;
	
	if(pAttrRecord->attr_count <= 0){
		return ID_ERR_NOERROR;
	}
	fprintf(fp,"<information name=\"%s_%d\" scheme=\"kokudo-digital-map-2500\"",
				pAttrRecord->code, pAttrRecord->id);
	
	fprintf(fp,">\n");
	
	fprintf(fp,"<%s id=\"%s\">\n",g_display_names_of_code[nCode], pAttrRecord->code);
	PrintXMLSubInformation(fp, nCode, pAttrRecord);
	fprintf(fp,"</%s>\n",g_display_names_of_code[nCode]);
	
	fprintf(fp,"</information>\n");
	
	return ID_ERR_NOERROR;
}

ATTR_RECORD *FindAttrRecordFromAttrDataByID(ATTR_DATA *pAttr, int nID){ 
	int i;
	for(i=0;i<pAttr->header.record_count;++i){
		if(pAttr->record[i].id == nID)
			return &pAttr->record[i];
	}
	return NULL;
}

void FindAndChangeArcIDAttr(ATTR_DATA *pAttr, int nOldID, int nNewID){
	int i;
	ATTR_RECORD *pRecord = pAttr->record;
	char **ppIDAttr = NULL;
	for(i=0; i<pAttr->header.record_count; ++i,++pRecord){
		if(pRecord->attr_count > 0){
			//kasen
			if(!strcmp(pRecord->code,"A5121") && 
				(pRecord->attr_count > 1) ){
				ppIDAttr = &(pRecord->pszAttrs[1]);
			}
			//douro
			else if(!strcmp(pRecord->code,"L2112") || !strcmp(pRecord->code,"L2101")){
				ppIDAttr = &(pRecord->pszAttrs[0]);
			}
			if(ppIDAttr && atoi(*ppIDAttr) == nOldID){
				char *szNewID = (char*)malloc(16);
				sprintf(szNewID, "%d", nNewID);
				free(*ppIDAttr);
				*ppIDAttr = szNewID;
				ppIDAttr = NULL;
			}
		}
	}
}


ATTR_DATA *malloc_attr_data(){
	ATTR_DATA *pData = (ATTR_DATA*)(malloc(sizeof(ATTR_DATA)));
	memset(pData,0,sizeof(ATTR_DATA));
	return pData;
}

void free_attr_record(ATTR_RECORD *pRecord){
	int i;
	for(i=pRecord->attr_count-1;i>=0;--i){
		free(pRecord->pszAttrs[i]);
	}
	pRecord->attr_count = 0;
}

void free_attr_data(ATTR_DATA *pData){
	if(!pData)
		return;
	if(pData->record != NULL){
		int i;
		for(i=0;i<pData->header.record_count;++i){
			free_attr_record(&(pData->record[i]));
		}
		free(pData->record);
	}
	free(pData);
}
