/*
 *  
 *  $Id: dicomservers.cpp $
 *  Ginkgo CADx Project
 *
 *  Copyright 2008-12 MetaEmotion S.L. All rights reserved.
 *  http://ginkgo-cadx.com
 *
 *  This file is licensed under LGPL v3 license.
 *  See License.txt for details
 *
 *
 */
#include "dicomservers.h"
#include <iostream>
#include <wx/filename.h>
#include <wx/file.h>
#include <wx/textfile.h>
#include <wx/dir.h>
#include <main/controllers/configurationcontroller.h>
#include <main/entorno.h>
#include <api/globals.h>

DicomServerList* DicomServerList::m_pInstance = 0;

DicomServerList::DicomServerList()
{
	serverHolders = NULL;
	localServer = NULL;
	lastInsertedHolder = NULL;
	Reload();
	//std::cout << "DicomServerList construido" << std::endl;
}

DicomServerList::~DicomServerList()
{
	//std::cout << "DicomServerList destruyendose" << std::endl;
	DicomServerHolder* holder = NULL;
	DicomServerHolder* tempHolder = NULL;
	for (holder = serverHolders; holder != NULL;) {
		tempHolder = holder->next;
		holder->next = NULL;
		delete holder;
		holder = tempHolder;
	}
	if (localServer != NULL) {
		delete localServer;
		localServer = NULL;
	}
	serverHolders = NULL;
	lastInsertedHolder = NULL;
	//std::cout << "DicomServerList destruido" << std::endl;
}

DicomServerList* DicomServerList::Instance()
{
	if (m_pInstance == NULL) {
		m_pInstance = new DicomServerList();
	}
	return m_pInstance;
}

void DicomServerList::FreeInstance()
{
	if (m_pInstance != NULL) {
		delete m_pInstance;
		m_pInstance = 0;
	}

}

void DicomServerList::AddServer(const DicomServer& newServer, bool isDefault)
{
	if (isDefault) {
		for (DicomServerHolder* sl = GetList(); sl != NULL; sl = sl->next) {
			sl->server.isDefault = false;
		}
	}
	if (TieneServer(newServer.ID)) {
		DicomServer* server = GetServer(newServer.ID);
		*server = newServer;
		server->isDefault = isDefault;
	}
	else {
		DicomServerHolder* newServerHolder = new DicomServerHolder(newServer.ID, newServer.AET, newServer.HostName, newServer.Port, newServer.Lossy, newServer.isDefault, newServer.PDU, newServer.useTLS, newServer.pacsUser, newServer.pacsPass, newServer.retrieveWithMove, newServer.retrieveSeries, newServer.reuseConnection, newServer.verifyCredentials, newServer.certificate, newServer.privateKey, newServer.defaultCharset);
		newServerHolder->server.isDefault = isDefault;
		if (serverHolders == NULL) {
			lastInsertedHolder = serverHolders = newServerHolder;
		} else {
			lastInsertedHolder->next = newServerHolder;
			lastInsertedHolder = lastInsertedHolder->next;
		}
	}
	
}

bool DicomServerList::TieneServer(const std::string& ID)
{
	DicomServerHolder* it;

	bool found = false;

	for (it = serverHolders; it != NULL && !found; it = it->next) {
		if (it->server.ID == ID) {
			found = true;
		}
	}

	return found;
}

DicomServer* DicomServerList::GetServer(const std::string& ID)
{
	DicomServer* server = NULL;

	DicomServerHolder* it;

	bool found = false;

	for (it = serverHolders; it != NULL && !found; it = it->next) {
		if (it->server.ID == ID) {
			found = true;
			server = &it->server;
		}
	}

	if (server == NULL) {
		throw GinkgoNoServerFoundException();
	}

	return server;
}

DicomServer* DicomServerList::GetLocalServer()
{
	if (localServer == NULL) {
		throw GinkgoNoServerFoundException();
	}
	return localServer;
}

DicomServerHolder* DicomServerList::GetList()
{
	return serverHolders;
}

DicomServer* DicomServerList::GetDefaultServer()
{
	if (serverHolders != NULL) {
		for (DicomServerHolder* it = serverHolders; it != NULL; it = it->next) {
			if (it->server.isDefault) {
				return &it->server;
			}
		}
	}
	if (serverHolders != NULL) {
		return &serverHolders->server;
	} else {
		return NULL;
	}
}

void DicomServerList::SetDefaultServer(const std::string& ID)
{
	if (serverHolders != NULL) {
		for (DicomServerHolder* it = serverHolders; it != NULL; it = it->next) {
			if (it->server.ID == ID) {
				it->server.isDefault = true;
			} else {
				it->server.isDefault = false;
			}
		}
	}
}

DicomServer* DicomServerList::GetFirst()
{
	DicomServer* server = NULL;
	if (serverHolders != NULL) {
		server = &serverHolders->server;
	}
	return server;
}

DicomServer* DicomServerList::GetLast()
{
	return &lastInsertedHolder->server;
}

void DicomServerList::Reload()
{
	DicomServerHolder* holder = NULL;
	DicomServerHolder* tempHolder = NULL;
	for (holder = serverHolders; holder != NULL;) {
		tempHolder = holder->next;
		holder->next = NULL;
		delete holder;
		holder = tempHolder;
	}
	if (localServer != NULL) {
		delete localServer;
		localServer = NULL;
	}
	serverHolders = NULL;
	lastInsertedHolder = NULL;

	GNC::GCS::ConfigurationController::TListGroups servers;
	GNC::GCS::ConfigurationController::Instance()->readGroupGeneral("/GinkgoCore/PACS/Servidores", servers);

	bool existDefault = false;
	for (GNC::GCS::ConfigurationController::TListGroups::iterator it = servers.begin(); it != servers.end(); ++it) {
		GNC::GCS::ConfigurationController::TMapValues& values = (*it);
		std::string id, aet, host;
		int port, pdu;
		values.readStringValue("Identificador", id);
		values.readStringValue("AET", aet);
		values.readStringValue("Host", host);
		values.readIntValue("Puerto", port);
		values.readIntValue("PDU", pdu, DEFAULT_PDU_LENGTH);

		DicomServer server(id, aet, host, port, 0, false, pdu, false, "", "", false, false, true, false, "", "", "");
		values.readBoolValue("isDefault",server.isDefault,false);
		values.readBoolValue("useTLS",server.useTLS,false);
		values.readStringValue("pacsUser", server.pacsUser);
		values.readStringValue("pacsPass", server.pacsPass);
		values.readBoolValue("verifyCredentials",server.verifyCredentials,false);
		values.readStringValue("certificate", server.certificate);
		values.readStringValue("privateKey", server.privateKey);
		values.readBoolValue("retrieveWithMove",server.retrieveWithMove,true);
		values.readBoolValue("reuseConnection", server.reuseConnection, false);
		values.readBoolValue("retrieveSeries",server.retrieveSeries,true);
		values.readStringValue("defaultCharset", server.defaultCharset, "ISO_IR 100");

		AddServer(server, server.isDefault);
		existDefault = existDefault || server.isDefault;
	}

	if (!existDefault) {
		if (serverHolders != NULL) {
			serverHolders->server.isDefault = true;
		}
	}

	//local server
	//se actualiza el fichero de configuracion
	int port;
	GNC::GCS::ConfigurationController::Instance()->readIntGeneral("/GinkgoCore/PACS/Local", "Puerto", port, 11112);
	std::string localAet = GNC::Entorno::Instance()->GetDicomLocalAET();
	
	localServer = new DicomServer("ginkgo",localAet, "localhost", port, 0, false, 16384,false, "", "", false, true,false, false, "", "", "");
	GNC::GCS::ConfigurationController::Instance()->readBoolGeneral("/GinkgoCore/PACS/Local", "useTLS", localServer->useTLS, false);
	GNC::GCS::ConfigurationController::Instance()->readBoolGeneral("/GinkgoCore/PACS/Local", "verifyCredentials", localServer->verifyCredentials, false);
#ifdef GINKGO_PRIVATE_KEY
	localServer->privateKey = GINKGO_PRIVATE_KEY;
#endif
	GNC::GCS::ConfigurationController::Instance()->readStringGeneral("/GinkgoCore/PACS/Local", "privateKey", localServer->privateKey);

#ifdef GINKGO_PUBLIC_KEY
	localServer->certificate = GINKGO_PUBLIC_KEY;
#endif
	GNC::GCS::ConfigurationController::Instance()->readStringGeneral("/GinkgoCore/PACS/Local", "certificate", localServer->certificate);
}

