/* ====================================================================
 * Copyright (c) 2003-2008        Martin Hauner
 *                                http://subcommander.tigris.org
 *
 * Subcommander is licensed as described in the file doc/COPYING, which
 * you should have received as part of this distribution.
 * ====================================================================
 */

// sc
#include "config.h"
#include "StatusId.h"
#include "ColorId.h"
#include "sublib/ColorStorage.h"
#include "util/String.h"

// qt
#include <QtCore/QHash>



/** status code mapping entry. */
struct StatusCode
{
  StatusId   _sid;   ///< just for documentation
  ColorId    _cid;
  sc::String _code;
  sc::String _name;
};

// we use the same chars here as subversion in:
// subversion/clients/cmdline/status.c:generate_status_code()

/** mapping table for status code to color, short code and name */
const StatusCode StatusCodes[] = 
{
  // general
  { StatusNone,          ColorNone,          sc::String(_n(" ")), sc::String(_n("none")) },
  { StatusUnversioned,   ColorUnversioned,   sc::String(_n("?")), sc::String(_n("unversioned")) },
  { StatusNormal,        ColorNormal,        sc::String(_n(" ")), sc::String(_n("unchanged")) },
  { StatusAdded,         ColorAdded,         sc::String(_n("A")), sc::String(_n("added")) },
  { StatusMissing,       ColorMissing,       sc::String(_n("!")), sc::String(_n("missing")) },
  { StatusDeleted,       ColorDeleted,       sc::String(_n("D")), sc::String(_n("deleted")) },
  { StatusReplaced,      ColorReplaced,      sc::String(_n("R")), sc::String(_n("replaced")) },
  { StatusModified,      ColorModified,      sc::String(_n("M")), sc::String(_n("modified")) },
  { StatusMerged,        ColorMerged,        sc::String(_n("G")), sc::String(_n("merged")) },
  { StatusConflicted,    ColorConflicted,    sc::String(_n("C")), sc::String(_n("conflicted")) },
  { StatusIgnored,       ColorIgnored,       sc::String(_n("I")), sc::String(_n("ignored")) },
  { StatusObstructed,    ColorObstructed,    sc::String(_n("~")), sc::String(_n("obstructed")) },
  { StatusExternal,      ColorExternal,      sc::String(_n("X")), sc::String(_n("external")) },
  { StatusIncomplete,    ColorIncomplete,    sc::String(_n("!")), sc::String(_n("incomplete")) },
  { StatusFallback,      ColorFallback,      sc::String(_n("-")), sc::String(_n("<fallback>")) },

  // working copy lock
  { StatusWcLockNone,    ColorNone,          sc::String(_n(" ")), sc::String(_n("not locked")) },
  { StatusWcLockLocked,  ColorNone,          sc::String(_n("L")), sc::String(_n("locked")) },

  // history
  { StatusHistoryNone,   ColorNone,          sc::String(_n(" ")), sc::String(_n("no history")) },
  { StatusHistory,       ColorNone,          sc::String(_n("+")), sc::String(_n("history")) },

  // switched
  { StatusSwitchedNo,    ColorNone,          sc::String(_n(" ")), sc::String(_n("not switched")) },
  { StatusSwitched,      ColorNone,          sc::String(_n("S")), sc::String(_n("switched")) },

  // switched
  { StatusUpToDateNo,    ColorNone,          sc::String(_n("*")), sc::String(_n("not up to date")) },
  { StatusUpToDate,      ColorNone,          sc::String(_n(" ")), sc::String(_n("up to date")) },

  // repository locks
  { StatusLockNone,      ColorNone,          sc::String(_n(" ")), sc::String(_n("not locked")) },
  { StatusLockLocked,    ColorNone,          sc::String(_n("K")), sc::String(_n("locked")) },
  { StatusLockStolen,    ColorNone,          sc::String(_n("T")), sc::String(_n("locked but stolen")) },
  { StatusLockOther,     ColorNone,          sc::String(_n("O")), sc::String(_n("locked in other wc")) },
  { StatusLockBroken,    ColorNone,          sc::String(_n("B")), sc::String(_n("not locked, broken")) }
};


QString getStatusCode( svn::WcStatusKind status )
{
  switch( status )
  {
  case svn::WcStatus_None:        return _q(StatusCodes[StatusNone]._code);
  case svn::WcStatus_Unversioned: return _q(StatusCodes[StatusUnversioned]._code);
  case svn::WcStatus_Normal:      return _q(StatusCodes[StatusNormal]._code);
  case svn::WcStatus_Added:       return _q(StatusCodes[StatusAdded]._code);
  case svn::WcStatus_Missing:     return _q(StatusCodes[StatusMissing]._code);
  case svn::WcStatus_Deleted:     return _q(StatusCodes[StatusDeleted]._code);
  case svn::WcStatus_Replaced:    return _q(StatusCodes[StatusReplaced]._code);
  case svn::WcStatus_Modified:    return _q(StatusCodes[StatusModified]._code);
  case svn::WcStatus_Merged:      return _q(StatusCodes[StatusMerged]._code);
  case svn::WcStatus_Conflicted:  return _q(StatusCodes[StatusConflicted]._code);
  case svn::WcStatus_Ignored:     return _q(StatusCodes[StatusIgnored]._code);
  case svn::WcStatus_Obstructed:  return _q(StatusCodes[StatusObstructed]._code);
  case svn::WcStatus_External:    return _q(StatusCodes[StatusExternal]._code);
  case svn::WcStatus_Incomplete:  return _q(StatusCodes[StatusIncomplete]._code);
  default:                        return _q(StatusCodes[StatusFallback]._code);
  }
}

QColor getStatusColor( svn::WcStatusKind status )
{
  switch( status )
  {
  case svn::WcStatus_None:        return ColorStorage::getColor(ColorNone);
  case svn::WcStatus_Unversioned: return ColorStorage::getColor(ColorUnversioned);
  case svn::WcStatus_Normal:      return ColorStorage::getColor(ColorNormal);
  case svn::WcStatus_Added:       return ColorStorage::getColor(ColorAdded);
  case svn::WcStatus_Missing:     return ColorStorage::getColor(ColorMissing);
  case svn::WcStatus_Deleted:     return ColorStorage::getColor(ColorDeleted);
  case svn::WcStatus_Replaced:    return ColorStorage::getColor(ColorReplaced);
  case svn::WcStatus_Modified:    return ColorStorage::getColor(ColorModified);
  case svn::WcStatus_Merged:      return ColorStorage::getColor(ColorMerged);
  case svn::WcStatus_Conflicted:  return ColorStorage::getColor(ColorConflicted);
  case svn::WcStatus_Ignored:     return ColorStorage::getColor(ColorIgnored);
  case svn::WcStatus_Obstructed:  return ColorStorage::getColor(ColorObstructed);
  case svn::WcStatus_External:    return ColorStorage::getColor(ColorExternal);
  case svn::WcStatus_Incomplete:  return ColorStorage::getColor(ColorIncomplete);
  default:                        return ColorStorage::getColor(ColorFallback);
  }
}

QString getLockStatusCode( svn::WcStatusLockKind status )
{
  static QHash< svn::WcStatusLockKind, QString > cache;

  if( cache.contains(status) )
    return cache.value(status);
  else
  {
    QString value;
    switch( status )
    {
    case svn::WcStatusLock_None:
      value = _q(StatusCodes[StatusLockNone]._code);
      break;
    case svn::WcStatusLock_Locked:
      value = _q(StatusCodes[StatusLockLocked]._code);
      break;
    case svn::WcStatusLock_Stolen:
      value = _q(StatusCodes[StatusLockStolen]._code);
      break;
    case svn::WcStatusLock_Other:
      value = _q(StatusCodes[StatusLockOther]._code);
      break;
    case svn::WcStatusLock_Broken:
      value = _q(StatusCodes[StatusLockBroken]._code);
      break;
    default:
      value = _q(StatusCodes[StatusFallback]._code);
    }
    cache.insert( status, value );
    return value;
  }

}

QString getStatusCode( StatusId id )
{
  return _q(StatusCodes[id]._code);
}

QString getStatusName( StatusId id )
{
  return _q(StatusCodes[id]._name);
}

QColor getStatusColor( StatusId id )
{
  return ColorStorage::getColor(StatusCodes[id]._cid);
}
