/***************************************************************************
 *   Copyright (C) 2005 by SUZUKI Tasuku                                   *
 *   tasuku@linux-life.net                                                 *
 *                                                                         *
 *   This program 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 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   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.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "kkaaddressmanagerjp.h"

#include <qregexp.h>
#include <qfile.h>
#include <qtextcodec.h>
#include <qfileinfo.h>
#include <qmap.h>

#include <kprocess.h>
#include <kdebug.h>
#include <klocale.h>
#include <kapplication.h>
#include <kglobal.h>
#include <kstandarddirs.h>
#include <kio/netaccess.h>
#include <kmessagebox.h>
#include <kprogress.h>

using namespace KKAddressBook;

KKAAddressManagerJP::KKAAddressManagerJP()
 : KKAAddressManager()
{
	m_datafile = locateLocal( "data", KGlobal::instance()->instanceName() + "/" + DATAFILE );
	if( available() ) cache();
}


KKAAddressManagerJP::~KKAAddressManagerJP()
{
}

QString KKAAddressManagerJP::mask()
{
	return "999-9999; ";
}

bool KKAAddressManagerJP::isEmpty( QString zipcode )
{
	return zipcode.replace( "-", "" ).isEmpty();
}

bool KKAAddressManagerJP::available()
{
	return QFile::exists( m_datafile );
}

void KKAAddressManagerJP::cache()
{
	QFile file( m_datafile );
	if( !file.open( IO_ReadOnly ) ){
		return;
	}

	m_data.clear();
	QTextStream ts( &file );
	while( !ts.atEnd() )
	{
		m_data.push_back( ts.readLine() );
	}
	file.close();
}

QString KKAAddressManagerJP::zipcode2address( QString zipcode )
{
	if( zipcode.length() != 8 ) return QString::null;
	
	int target = zipcode.replace( "-", "" ).toInt();
	int left = 0;
	int right = m_data.size();
	int mid;
	
	while( left <= right )
	{
		mid = ( left + right ) / 2;
		int str = m_data[mid].left( m_data[mid].find( '\t' ) ).toInt();
		if( str == target )
		{
			return m_data[mid].mid( m_data[mid].find( '\t' )+1 );
		}
		else if( str < target )
		{
			left = mid + 1;
		}
		else
		{
			right = mid - 1;
		}
	}
	return QString::null;
}

void KKAAddressManagerJP::readConfig( KConfig* conf )
{
	conf->setGroup( "KKAAddressManagerJP" );
}

void KKAAddressManagerJP::saveConfig( KConfig* conf )
{
	conf->setGroup( "KKAAddressManagerJP" );
}

/**
 * @japanese
 * LHA の存在チェック
 * @endjapanese
 */
bool KKAAddressManagerJP::checkLha( QWidget* parent )
{
	KProcess* proc = new KProcess( parent );
	*proc << "which" << "lha";
	proc->start();
	while( proc->isRunning() )
	{
		kapp->processEvents();
	}
	if( proc->exitStatus() != 0 )
	{
		KMessageBox::error( parent, i18n( "Japanese zipcode dictionary is lzh archive\nPlease install lha." ) );
		return false;
	}
	return true;
}

bool KKAAddressManagerJP::setup( QWidget* parent )
{
	if( !checkLha( parent ) ) return false;

	int ans = KMessageBox::questionYesNo( parent, i18n( "Do you want to download zipcode data?" ), i18n( "setup" ), KStdGuiItem::yes(), KStdGuiItem::no(), "kk_zipcode_setup_jp" );
	if( ans != KMessageBox::Yes ) return false;
	QString tmpfile;
	KProgressDialog* dlg = new KProgressDialog( parent, "", i18n( "ZipCode Update" ), "Test", true );
	dlg->setAllowCancel( true );
	dlg->progressBar()->setTotalSteps( 47 );
	dlg->setLabel( i18n( "download zipcode archive" ) );
	dlg->show();

	if( !KIO::NetAccess::download( JAPANPOST, tmpfile, parent ) )
	{
		delete dlg;
		KMessageBox::sorry( parent, KIO::NetAccess::lastErrorString() );
		return false;
	}
	dlg->setLabel( i18n( "expand zipcode archive" ) );

	KProcess* proc = new KProcess( parent );
	*proc << "lha" << "xq2" << tmpfile;
	proc->start();
	while( proc->isRunning() )
	{
		kapp->processEvents();
	}
	KIO::NetAccess::removeTempFile( tmpfile );

	QFile org( "ken_all.csv" );
	if( !org.open( IO_ReadOnly ) ){
		KMessageBox::sorry( parent, i18n( "Could not open %1" ).arg( org.name() ) );
		return false;
	}

	QTextStream in( &org );
	in.setCodec( QTextCodec::codecForName("Shift-JIS") );

	QMap<int,QString> map;
	QString pref = QString::null;
	int i = -1;
	while( !in.atEnd() )
	{
		kapp->processEvents();
		if( dlg->wasCancelled() ) break;
		QStringList fields = QStringList::split( ',', in.readLine() );
		QString code = fields[2].replace( "\"", "" );
		QString address = fields[6] + fields[7];
		if( fields[8] == QString::fromUtf8( "\"以下に掲載がない場合\"" ) )
		{
			// exception
		}
		else if( fields[8].find( QString::fromUtf8( "（" ) ) != -1 )
		{
			// exception
		}
		else
		{
			address += fields[8];
		}
		address = address.replace( "\"", "" );
		map[code.toInt()] = address;
		if( pref != fields[6] )
		{
			pref = fields[6];
			dlg->setLabel( fields[6].replace( "\"", "" ) );
			kapp->processEvents();
			dlg->progressBar()->setProgress( i++ );
		}
	}
	
	QValueList<int> key = map.keys();
	m_data.clear();
	qHeapSort( key );
	
	QFile local( m_datafile );
	if( !local.open( IO_WriteOnly ) ){
		KMessageBox::sorry( parent, i18n( "Could not open %1" ).arg( m_datafile ) );
		org.close();
		return false;
	}
	QTextStream out( &local );
	for( QValueList<int>::const_iterator it = key.begin(); it != key.end(); ++it )
	{
		out << *it << '\t' << map[*it] << endl;
		m_data.push_back( QString( "%1\t%2" ).arg( *it ).arg( map[*it] ) );
	}
	kapp->processEvents();
	dlg->close();
	org.close();
	local.close();
	org.remove();
	return true;
}

KKAAddressManagerJPDialog::KKAAddressManagerJPDialog( QWidget* parent, const char* name )
	: KDialogBase( parent, name, true, i18n( "setup" ), Ok|Cancel )
{
}

KKAAddressManagerJPDialog::~KKAAddressManagerJPDialog()
{
}
