#include <stdio.h>
#include <string.h>
#include <process.h>
#include <malloc.h>
#include <stdlib.h>
#include <ERRNO.H>

#include <windows.h>
#include <shellapi.h>

/* not support multibyte pathname */

void chop(char *str){
int len = strlen(str);
	if(str[len-1] == '\n'){
		if(str[len-2] == '\r'){
			str[len-2] = '\0';
		}
		else{
			str[len-1] = '\0';
		}
	}
}

void change_path_delim(char *path){
int i;
	for(i=0;i<strlen(path);++i){
		if(path[i]=='\\'){
			path[i]='/';
		}
	}
}

void append_filename_to_buff(char **buff, int *buff_size, const char *filename){
	while(strlen(*buff)+strlen(filename) >= (unsigned int)(*buff_size-1)){
		*buff_size *= 2;
		*buff = (char*)realloc(*buff, *buff_size);
	}
	strcat(*buff, filename);
	strcat(*buff, "\t");
}


void listup_file(char **ret, int *buff_size, const char *dir){
	
	WIN32_FIND_DATA fd;
	char filter[MAX_PATH+1];
	char fullpath[MAX_PATH+1];
	HANDLE hFind;
	
	sprintf(filter, "%s\\*.*", dir);
	hFind = FindFirstFile(filter, &fd);
	if(hFind == INVALID_HANDLE_VALUE)
		return;
	do{
		if(*(fd.cFileName) == '.'){
			continue;
		}
		
		sprintf(fullpath, "%s\\%s", dir, fd.cFileName);
		
		if(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY){
			listup_file(ret, buff_size, fullpath);
			continue;
		}
		else{
			char *ext = strrchr(fullpath, '.');
			if(ext){
				if((strcmp(ext, ".c") == 0) ||
					(strcmp(ext, ".cpp") == 0) ||
					(strcmp(ext, ".h") == 0)
					){
					change_path_delim(fullpath);
					append_filename_to_buff(ret, buff_size, fullpath);
				}
			}
		}
	}while(FindNextFile(hFind, &fd));
	
	FindClose(hFind);
}

	

void str2file(const char*file, const char*str){
	FILE *fp;
	fp = fopen(file, "w");
	if(!fp){
		fprintf(stderr, "cannt open file for write %s", file);
		exit(1);
	}
	fwrite(str, strlen(str), 1, fp);
	fclose(fp);
}

void convert_pathname(const char *parent_dir, const char*dsp_path,  const char *src, char *dest){
	const char *ptr;
	char *from_=0;
	int i=0,j=0;
	int count=0;
	const char *src_;
	char src_buff[MAX_PATH];
	
	strcpy(src_buff, src);
	
	change_path_delim(src_buff);
	count= 0;
	src_ = src_buff;
	/* get ../ count */
	for(ptr = src_buff; ptr;){
		if(ptr = strstr(ptr, "../")){
			ptr += 3;
			src_ = ptr;
			++count;
		}
	}
	
	if(count){
		i=0;
		for(j = strlen(parent_dir)-1; i<count; --j){
			if(j<0){
				printf("invalid filepath : src=%s  dest=%s\n", src, dest);
				exit(1);
			}
			if(parent_dir[j] == '/'){
				++i;
				if(i>=count)
					break;
			}
		}
		sprintf(dest, "%s/%s", &parent_dir[j], src_);
	}
	else{
		sprintf(dest, "%s/%s", &parent_dir[j], src_);
	}
	
}

int directory_count(const char *path){
	int ret=0;
	while(*path){
		if(*path=='\\' || *path=='/'){
			++ret;
		}
		++path;
	}
	return ret;
}

void extract_path(char *path, char*full_path){
	char *p;
	strcpy(path, full_path);
	p=strrchr(path,'/');
	if(p){
		*(p+1) = '\0';
	}
}


int main(int argc, char* argv[])
{
	FILE *fp;
	char line[65536];
	char parent_dir[MAX_PATH];
	
	char *mversion_argnames[32];
	char *mversion_argvalues[32];
	int i;
	char *source_files;
	int buff_size; 
	char *source_dir=0;
	char *dsp_name=0;

#ifdef _DEBUG
	SetCurrentDirectory("../../../env/proj/win");
#endif
	GetCurrentDirectory(sizeof(parent_dir), parent_dir);
	*strrchr(parent_dir, '\\') = '\0';
	
	change_path_delim(parent_dir);
	
	memset(mversion_argnames, 0, sizeof(mversion_argnames));
	memset(mversion_argvalues, 0, sizeof(mversion_argvalues));
	
	if(argc < 2){
		printf("usage: win_mversion xxx.conf");
		return 0;
	}
	
	fp = fopen(argv[1], "r");
	if(!fp){
		printf("error open file %s\n", argv[2]);
		return 2;
	}
	i = 0;
	while(fgets(line, sizeof(line), fp)){
		char *token1, *token2;
		chop(line);
		
		token1 = strtok(line, "\t =");
		if(token1 == NULL)
			continue;
		token2 = strtok(NULL, "\r\n");
		if(token2 == NULL)
			continue;
		
		if(strcmp(token1, "dsp") == 0){
			dsp_name = strdup(token2);
			continue;
		}
		if(strcmp(token1, "source_dir") == 0){
			source_dir = strdup(token2);
			continue;
		}
		
		mversion_argnames[i] = strdup(token1);
		mversion_argvalues[i++] = strdup(token2);
	}
	fclose(fp);
	
	if(dsp_name){
		fp = fopen(dsp_name, "r");
		if(!fp){
			printf("error open file %s\n", dsp_name);
			return 1;
		}
		/* extract_path(dsp_path, dsp_name); */
		
		buff_size = 256;
		source_files = (char*)malloc(buff_size);
		source_files[0] = '\0';
		while(fgets(line, sizeof(line), fp)){
			char *ext;
			int len = strlen(line);
			chop(line);
			len = strlen(line);
			
			if(strncmp(line, "SOURCE=", 7) != 0)
				continue;
			
			ext = strrchr(line, '.');
			if(!ext)
				continue;
			if(
				(strcmp(ext, ".c") == 0) ||
				(strcmp(ext, ".cpp") == 0) ||
				(strcmp(ext, ".h") == 0)
				){
				change_path_delim(&line[7]);
				append_filename_to_buff(&source_files, &buff_size, &line[7]);
			}
		}
		
		fclose(fp);
	}
	else if(source_dir){
		buff_size = 256;
		source_files = (char*)calloc(1,buff_size);
		listup_file(&source_files, &buff_size, source_dir);
	}
	else{
		fprintf(stderr, " 'dsp' or 'source_dir' needs in configure file \n");
		exit(1);
	}
	
	
	{
		char *command_line;
		int len;

		len = strlen("mversion ");
		for(i=0; mversion_argvalues[i]; ++i){
			len += strlen("-");
			len += strlen(mversion_argnames[i]);
			len += strlen(" ");
			len += strlen(mversion_argvalues[i]);
			len += strlen(" ");
		}
		len += strlen(" -source ");
		len += strlen(source_files);
		
		command_line = (char*)malloc(len+1);
		command_line[0] = '\0';

		strcat(command_line, "mversion ");
		for(i=0; mversion_argvalues[i]; ++i){
			strcat(command_line, "-");
			strcat(command_line, mversion_argnames[i]);
			strcat(command_line, " ");
			strcat(command_line, mversion_argvalues[i]);
			strcat(command_line, " ");
		}
		strcat(command_line, " -source ");
		strcat(command_line, source_files);
		
		str2file("mversion.argv", command_line);
		system("mversion mversion.argv");
		
		/*
		if(32 >= ShellExecute(NULL, "open", "mversion", command_line, NULL, SW_SHOWDEFAULT)){
			printf("***error***\n");
		}
		*/
		free(command_line);
		
	}
	free(source_files);
	return 0;
}
