/*********************************************************
** Copyright (c) 2005
** University of Washington
** Licensed under the terms set forth by University of
** Washington. If you did not sign such a license, you
** are using this software/code illegally and you do not
** have permission to use, modify, or redistribute
** this or any files in this software package.
**
** File: ClusterThread.cpp
**
**********************************************************/
#include "ClusterThread.h"
#include "ClusterException.h"

// debug
#include <stdio.h>

/*
 * This function does all the work.
 */
int CClusterThread::Go(THREAD_ID_T tid)
{
  int status = 0;
  try
    {
      /* Cluster the data */
      m_pResult = m_pCluster->Cluster((void**)m_pInData, m_dataCount);
      if (NULL == m_pResult)
	return -1;
      
      /* Order the data, if requested */
      if (NULL != m_pOrdering)
	{
	  m_pOrdering->OrderLeaves(m_pResult, m_pCluster->GetDistanceMatrix());
	}
    }
  catch(CClusterException* pEx)
    {
      status = pEx->Id();
      /* Save the error message for later retrieval */
      SetErrorMessage(pEx->Message());
    }

 return status;
}

/*
 * Creates a CClusterThread object.
 * Arguments:
 *   pCluster : Pointer to an object that implements the clustering algorithm
 *   pData : The data to cluster
 *   dataCount : The number of rows of data
 *   pOrdering : Pointer to an object that implements the ordering algorithm
 *   deleteAll : If true, deleting this object also deletes pCluster and 
 *      pOrdering. Useful for "set and forget"... 
 */
CClusterThread::CClusterThread(CCluster* pCluster, TDoubleVector** pData, int dataCount, COrdering *pOrdering, bool deleteAll)
  : m_pCluster(pCluster), m_pInData(pData), m_dataCount(dataCount), m_pOrdering(pOrdering),
    m_bDeleteAll(deleteAll),  m_pResult(NULL)
// gah - be sure to initialize m_pResult to NULL!
{
}

/*
 * Frees resources associated with a CClusterThread object.
 */
CClusterThread::~CClusterThread()
{
  if(m_bDeleteAll)
    {
      if (NULL != m_pInData)
	{
	  for(int i = 0; i < m_dataCount; i++)
	    delete m_pInData[i];
	  delete m_pInData; 
	  m_dataCount = 0;
	  m_pInData = NULL;
	}
      if (NULL != m_pCluster)
	{
	  // TODO: delete pCluster's Distance & Linkage objects
	  delete m_pCluster->GetDistanceFunction();
	  delete m_pCluster->GetCombineDataFunction();
	  delete m_pCluster;
	  m_pCluster = NULL;
	}
      if (NULL != m_pOrdering)
	{
	  delete m_pOrdering;
	  m_pOrdering = NULL;
	}
    }
  if (NULL != m_pResult)
    {
      m_pResult->RecursiveDelete();
      delete m_pResult;
    }
  m_pResult = NULL;
}

/*
 * Cleans up in case of unexpected thread termination.
 */
void CClusterThread::CleanupForTermination()
{
}

