/* Copyright 2013 Akira Ohta (akohta001@gmail.com)
    This file is part of ntch.

    The ntch is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    The ntch 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.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with ntch.  If not, see <http://www.gnu.org/licenses/>.
    
*/
#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
#include <string.h>
#include <assert.h>

#include "utils/nt_std_t.h"
#include "utils/text.h"


wchar_t* nt_w_str_resize(wchar_t *old_src, size_t old_size, size_t new_size)
{
	wchar_t *wrk_buf;
	
	assert(old_size < new_size && new_size > 0);
	
	wrk_buf = malloc(sizeof(wchar_t) * (new_size));
	if(!wrk_buf){
		return NULL;
	}
	
	if(!old_src){
		wrk_buf[0] = L'\0';
		return wrk_buf;
	}
	wmemcpy(wrk_buf, old_src, old_size);
	wrk_buf[old_size] = L'\0';
	free(old_src);
	return wrk_buf;
}

BOOL nt_w_str_move(wchar_t *buf, size_t buf_len, 
					int move_index, int offset)
{
	int str_len, tmp, i;
	assert(buf);

	str_len = wcslen(buf);

	if(0 > move_index || str_len <= move_index)
		return FALSE;

	tmp = str_len + offset;
	if(tmp >= buf_len)
		return FALSE;

	if(offset == 0){
	// Do nothing.
		return TRUE;
	}else if(offset < 0){
	// Move the block to forward.
		if(move_index + offset < 0)
			return FALSE;
		//str_len += offset;
		for(i = move_index; i < str_len; i++){
			buf[i+offset] = buf[i];
		}
		buf[str_len+offset] =  L'\0';
	}else{/* if(offset > 0) */
	// Move the block to backward.
		if(str_len + offset >= buf_len)
			return FALSE;
		for(i = str_len - 1; i >= move_index; i--){
			buf[i + offset] = buf[i];
		}
		buf[str_len + offset] = L'\0';
		buf[move_index] = L'\0';
	}
	return TRUE;
}



wchar_t *nt_w_trim(const wchar_t *source)
{
	int i, j, status;
	wchar_t *cptr;
	int len;

	assert(source != NULL);

	len = wcslen(source);

	for(i=0; i<len; i++){
		switch(source[i]){
		case L' ':
		case L'\t':
		case L'\r':
		case L'\n':
			status = 1;
			break;
		default:
			status = 0;
			break;
		}
		if(status == 0)
			break;
	}/* end for */
	if(i == len){
		cptr = malloc(sizeof(wchar_t));
		if(cptr != NULL)
			cptr[0] = L'\0';
		return cptr;
	}
	for(j = len - 1; j > i; j--){
		switch(source[j]){
		case L' ':
		case L'\t':
		case L'\r':
		case L'\n':
			status = 1;
			break;
		default:
			status = 0;
			break;
		}
		if(status == 0)
			break;
	}/* end for */
	assert(i <= j);
	len = j - i + 1;
	cptr = malloc(sizeof(wchar_t)*(len + 1));
	if(cptr != NULL){
		memcpy(cptr, source+i, len*sizeof(wchar_t));
		cptr[len] = '\0';
	}
	return cptr;
}

wchar_t *nt_w_trim_quotes(const wchar_t *source)
{
	assert(source != NULL);
	int len = wcslen(source);
	int i, j, status = 0;
	wchar_t *cptr;
	BOOL dquote = FALSE;
	BOOL squote = FALSE;

	for(i=0; i<len; i++){
		switch(source[i]){
		case L' ':
		case L'\t':
		case L'\r':
		case L'\n':
			if(status == 2){
				status = 0;
				break;
			}
			status = 1;
			break;
		case '\"':
			dquote = TRUE;
			status = 2;
			break;
		case '\'':
			squote = TRUE;
			status = 2;
			break;
		default:
			status = 0;
			break;
		}
		if(status == 0)
			break;
	}/* end for */
	if(i == len){
		cptr = malloc(sizeof(wchar_t));
		if(cptr != NULL)
			cptr[0] = L'\0';
		return cptr;
	}
	for(j = len - 1; j > i; j--){
		switch(source[j]){
		case L' ':
		case L'\t':
		case L'\r':
		case L'\n':
			if(status == 2)
				status = 0;
			else
				status = 1;
			break;
		case '\"':
			if(!dquote)
				status = 0;
			else
				status = 2;
			break;
		case '\'':
			if(!squote)
				status = 0;
			else
				status = 2;
			break;
		default:
			status = 0;
			break;
		}
		if(status == 0)
			break;
	}/* end for */
	len = j - i + 1;
	if(i < j){
		cptr = malloc(sizeof(wchar_t)*(len + 1));
		if(cptr != NULL){
			memcpy(cptr, source+i, len*sizeof(wchar_t));
			cptr[len] = L'\0';
		}
	}else{
		cptr = malloc(sizeof(wchar_t));
		if(cptr != NULL){
			cptr[0] = L'\0';
		}
	}
	return cptr;
}

char *nt_trim2(const char *source, char *buf, size_t buf_len)
{
	int i, j, status;
	char *cptr;
	int len;

	assert(source != NULL);

	len = strlen(source);

	if(!buf){
		cptr = calloc(len+1, sizeof(char));
		if(!cptr)
			return NULL;
	}else{
		if(buf_len < len+1)
			return NULL;
		cptr = buf;
	}
	for(i=0; i<len; i++){
		switch(source[i]){
		case ' ':
		case '\t':
		case '\r':
		case '\n':
			status = 1;
			break;
		default:
			status = 0;
			break;
		}
		if(status == 0)
			break;
	}/* end for */
	if(i == len){
		cptr[0] = L'\0';
		return cptr;
	}
	for(j = len - 1; j > i; j--){
		switch(source[j]){
		case ' ':
		case '\t':
		case '\r':
		case '\n':
			status = 1;
			break;
		default:
			status = 0;
			break;
		}
		if(status == 0)
			break;
	}/* end for */
	assert(i <= j);
	len = j - i + 1;
	memcpy(cptr, source+i, len*sizeof(char));
	cptr[len] = '\0';
	return cptr;
}

wchar_t* nt_w_str_clone(const wchar_t* src)
{
	wchar_t *cptr;
	cptr = malloc(sizeof(wchar_t) * (wcslen(src)+1));
	if(!cptr)
		return NULL;
	wcscpy(cptr, src);
	return cptr;
}

char* nt_str_clone(const char* src)
{
	char *cptr;
	cptr = malloc(strlen(src)+1);
	if(!cptr)
		return NULL;
	strcpy(cptr, src);
	return cptr;
}

char* nt_substr(const char* src, int start, int end)
{
	char *cptr;
	int len;

	assert(start >= 0);
	assert(start <= end);

	len = end - start;
	cptr = malloc(len + 1);
	if(!cptr)
		return NULL;
	
	if(len == 0){
		*cptr =  '\0';
		return cptr;
	}
	
	memcpy(cptr, src+start, len);
	cptr[len] = '\0';
	return cptr;
}

wchar_t* nt_w_substr(const wchar_t* src, int start, int end)
{
	wchar_t *cptr;
	int len;

	assert(start >= 0);
	assert(start <= end);

	len = end - start;
	cptr = malloc((len + 1)*sizeof(wchar_t));
	if(!cptr)
		return NULL;
	
	if(len == 0){
		*cptr =  L'\0';
		return cptr;
	}
	
	wmemcpy(cptr, src+start, len);
	cptr[len] = L'\0';
	return cptr;
}

BOOL nt_strtok(const char *str, char delim,
        const char** start, const char **end)
{
	int i, len, state;

	assert(str);

	len = strlen(str);
	*start = str;
	*end = str + len;

	state = 0;
	for(i = 0; i < len; i++){
		if(str[i] == delim){
			if(state == 0){
				*start = str + i + 1;
			}else if(state == 1){
				*end = str + i;
				return TRUE;
			}
		}else{
			if(state == 0)
				state = 1;
		}
	}
	return (*start < *end) ? TRUE : FALSE;
}

BOOL nt_w_strtok(const wchar_t *str, wchar_t delim,
        const wchar_t** start, const wchar_t **end)
{
	int i, len, state;

	assert(str);

	len = wcslen(str);
	*start = str;
	*end = str + len;

	state = 0;
	for(i = 0; i < len; i++){
		if(str[i] == delim){
			if(state == 0){
				*start = str + i + 1;
			}else if(state == 1){
				*end = str + i;
				return TRUE;
			}
		}else{
			if(state == 0)
				state = 1;
		}
	}
	return (*start < *end) ? TRUE : FALSE;
}

BOOL nt_itowc(wchar_t *buf, size_t buf_len, int number)
{
	int num, mod;
	int i, idx;
	
	num = number;
	idx = 1;
	buf[buf_len - idx] = L'\0';
	
	do{
		mod = num % 10;
		num = num / 10;
		if(buf_len == ++idx)
			return FALSE;
		
		buf[buf_len - idx] = L'0' + mod;
	}while(num);
	
	for(i = 0; i < idx; i++){
		buf[i] = buf[buf_len - idx + i];
	}
	return TRUE;
}
