 /*
** 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "stdafx.h"

#include "BrowseViewModel.h"
#include "Persistent.h"
#include "CvsEntries.h"

#if qMacPP
#	include "MacMisc.h"
#endif

static CPersistentBool persistentChanged("P_ViewChanged", false);
static CPersistentBool persistentAdded("P_ViewAdded", false);
static CPersistentBool persistentRemoved("P_ViewRemoved", false);
static CPersistentBool persistentConflicts("P_ViewConflicts", false);
static CPersistentBool persistentUnknown("P_ViewUnknown", false);
static CPersistentBool persistentHideUnknown("P_ViewHideUnknown", false);
static CPersistentBool persistentMissing("P_ViewMissing", false);
static CPersistentBool persistentHideMissing("P_ViewHideMissing", false);

static CPersistentBool persistentRecursive("P_DisplayRecursive", false);

static CPersistentBool persistentIgnore("P_FileViewIgnore", true);
	
//////////////////////////////////////////////////////////////////////////
// KoFilterModel

KoFilterModel::KoFilterModel()
	: m_filters(kFilterNone)
{
	m_filters |= persistentChanged		? kFilterChanged : 0;
	m_filters |= persistentAdded		? kFilterAdded : 0;
	m_filters |= persistentRemoved		? kFilterRemoved : 0;
	m_filters |= persistentConflicts	? kFilterConflicts : 0;
	m_filters |= persistentMissing		? kFilterMissing : 0;
	m_filters |= persistentHideMissing	? kFilterHideMissing : 0;
	m_filters |= persistentUnknown		? kFilterUnknown : 0;
	m_filters |= persistentHideUnknown	? kFilterHideUnknown : 0;
}

KoFilterModel::~KoFilterModel()
{
	persistentChanged		= HasFilter(kFilterChanged);
	persistentAdded			= HasFilter(kFilterAdded);
	persistentRemoved		= HasFilter(kFilterRemoved);
	persistentConflicts		= HasFilter(kFilterConflicts);
	persistentMissing		= HasFilter(kFilterMissing);
	persistentHideMissing	= HasFilter(kFilterHideMissing);
	persistentUnknown		= HasFilter(kFilterUnknown);
	persistentHideUnknown	= HasFilter(kFilterHideUnknown);
}

/// Check whether the filter is in default mode - to show flags are set
bool KoFilterModel::IsDefaultMode() const
{
	return !((kFilterConflicts | kFilterChanged | kFilterMissing | kFilterAdded | kFilterRemoved) & m_filters);
}

bool KoFilterModel::IsMatch(EntnodeData* data)
{
	// Check to see if file name matches
	if( m_match.size() && !MatchIgnoredList(data->GetName(), m_match) )
	{
		return false;
	}

	if( IsDefaultMode() && !HasFilter(kFilterUnknown) )
	{
		// Check if unknown files are to be hidden
		if( data->IsUnknown() && HasFilter(kFilterHideUnknown) )
		{
			// Unknown item match
			return false;
		}

		if( data->IsMissing() && HasFilter(kFilterHideMissing) )
		{
			// Hide missing item match
			return false;
		}
		
		return true;
	}
	
	if( data->IsMissing() && data->IsRemoved() && HasFilter(kFilterRemoved) )
	{
		// Removed item match
		return true;
	}

	if( data->IsMissing() && !data->IsRemoved() && HasFilter(kFilterMissing) )
	{
		// Missing item match
		return true;
	}

	if( data->IsUnknown() && HasFilter(kFilterUnknown) )
	{
		// Unknown item match
		return true;
	}

	if( (data->GetConflict() != NULL) && HasFilter(kFilterConflicts) )
	{
		// Conflict match
		return true;
	}

	if( !data->IsUnmodified() )
	{
		// Can be either changed or added 
		const char* vn = (*data)[EntnodeFile::kVN];
		const bool isAdded = vn && (strcmp(vn, "0") == 0);
		
		if( isAdded && HasFilter(kFilterAdded) )
		{
			// Added file match
			return true;
		}

		if( !isAdded && HasFilter(kFilterChanged) )
		{
			// Changed file match
			return true;
		}
	}

	// No match
	return false;
}

/*!
	Check whether any filters are active
	\return true if any filter is active, false otherwise
	\note File mask is not considered a filter
*/
bool KoFilterModel::HasFilters() const
{
	return kFilterNone != m_filters;
}

/*!
	Check whether any of the modified filters are active
	\return true if any modified filter is active, false otherwise
*/
bool KoFilterModel::HasAnyModified() const
{
	return kFilterNone != (kFilterModified & m_filters);
}

/*!
	Clear all filters
*/
void KoFilterModel::ClearAll()
{
	m_filters = kFilterNone;
}

/// Toggle modified flag
void KoFilterModel::ToggleModified()
{
	if( IsModified() )
	{
		m_filters &= ~kFilterModified;
	}
	else
	{
		m_filters |= kFilterModified;
	}
}

/// Get the modified flag
bool KoFilterModel::IsModified() const
{
	return (kFilterModified & m_filters) == kFilterModified;
}

NotificationManager* KoFilterModel::GetNotificationManager()
{
	return &m_manager;
}

int KoFilterModel::GetFilters() const
{
	return m_filters;
}

/*!
	Set new file mask
	\param fileMask File mask to be set
	\return true if file mask was changed, false otherwise
*/
bool KoFilterModel::SetMask(const char* fileMask)
{
	bool changed = m_mask.empty() || fileMask == 0L || stricmp(m_mask, fileMask) != 0;
	if( changed )
	{
		m_mask = fileMask;
		m_match.clear();

		if( !m_mask.empty() )
		{
			// Build match list 
			UStr mask = fileMask;
			char* buffer = mask;
			static const char separators[] = " \t;";
			
			for(char* token = strtok(buffer, separators); token; token = strtok(NULL, separators))
			{
				m_match.push_back(UStr(token));
			}
		}		
	}

	return changed;
}

/// Check whether the given filter is set
bool KoFilterModel::HasFilter(const int filter) const
{
	return (m_filters & filter) != 0;
}

/// Toggle specified filter
void KoFilterModel::ToggleFilter(int filter)
{
	if( HasFilter(filter) )
	{
		m_filters &= ~filter;
	}
	else
	{
		m_filters |= filter;
	}
}

/// Toggle show conflict flag
void KoFilterModel::ToggleConflict()
{
	ToggleFilter(kFilterConflicts);
}

/// Get the show conflict flag
bool KoFilterModel::IsConflict() const
{
	return HasFilter(kFilterConflicts);//m_isConflicts;
}

/// Toggle show unknown flag
void KoFilterModel::ToggleUnknown()
{
	ToggleFilter(kFilterUnknown);

	if( HasFilter(kFilterUnknown) )
	{
		m_filters &= ~kFilterHideUnknown;
	}
}

/// Get the show unknown flag
bool KoFilterModel::IsUnknown() const
{
	return HasFilter(kFilterUnknown);// m_isUnknown;
}

/// Toggle hide unknown flag
void KoFilterModel::ToggleHideUnknown()
{
	ToggleFilter(kFilterHideUnknown);

	if( HasFilter(kFilterHideUnknown) )
	{
		m_filters &= ~kFilterUnknown;
	}
}

/// Get the hide unknown flag
bool KoFilterModel::IsHideUnknown() const
{
	return HasFilter(kFilterHideUnknown);// m_isHideUnknown;
}

/// Toggle show missing flag
void KoFilterModel::ToggleMissing()
{
	ToggleFilter(kFilterMissing);

	if( HasFilter(kFilterMissing) )
	{
		m_filters &= ~kFilterHideMissing;
	}
}

/// Get the show missing flag
bool KoFilterModel::IsMissing() const
{
	return HasFilter(kFilterMissing);
}

/// Toggle hide missing flag
void KoFilterModel::ToggleHideMissing()
{
	ToggleFilter(kFilterHideMissing);

	if( HasFilter(kFilterHideMissing) )
	{
		m_filters &= ~kFilterMissing;
	}
}

/// Get the hide missing flag
bool KoFilterModel::IsHideMissing() const
{
	return HasFilter(kFilterHideMissing);
}

/// Toggle changed flag
void KoFilterModel::ToggleChanged()
{
	ToggleFilter(kFilterChanged);
}

/// Get the changed flag
bool KoFilterModel::IsChanged() const
{
	return HasFilter(kFilterChanged);
}

/// Toggle added flag
void KoFilterModel::ToggleAdded()
{
	ToggleFilter(kFilterAdded);
}

/// Get the added flag
bool KoFilterModel::IsAdded() const
{
	return HasFilter(kFilterAdded);
}

/// Toggle removed flag
void KoFilterModel::ToggleRemoved()
{
	ToggleFilter(kFilterRemoved);
}

/// Get the removed flag
bool KoFilterModel::IsRemoved() const
{
	return HasFilter(kFilterRemoved);
}

//////////////////////////////////////////////////////////////////////////
// KoRecursionModel

KoRecursionModel::KoRecursionModel()
	: m_isRecursive(persistentRecursive)
{
}

KoRecursionModel::~KoRecursionModel()
{
	persistentRecursive = m_isRecursive;
}

NotificationManager* KoRecursionModel::GetNotificationManager()
{
	return &m_manager;
}

/// Get the show recursive flag
bool KoRecursionModel::IsShowRecursive()
{
	return m_isRecursive;
}

/// Toggle recursion flag
void KoRecursionModel::ToggleRecursion()
{
	m_isRecursive = !m_isRecursive;
}

//////////////////////////////////////////////////////////////////////////
// KoIgnoreModel

KoIgnoreModel::KoIgnoreModel()
	: m_isIgnore(persistentIgnore)
{
}

KoIgnoreModel::~KoIgnoreModel()
{
	persistentIgnore = m_isIgnore;
}

NotificationManager* KoIgnoreModel::GetNotificationManager()
{
	return &m_manager;
}

/// Get the show ignored flag
bool KoIgnoreModel::IsShowIgnored()
{
	return m_isIgnore;
}

/// Toggle show ignored flag
void KoIgnoreModel::ToggleIgnore()
{
	m_isIgnore = !m_isIgnore;
}
