/*
  This file is part of the kcalutils library.

  Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
  Copyright (c) 2004 Reinhold Kainhofer <reinhold@kainhofer.com>
  Copyright (c) 2005 Rafal Rzepecki <divide@users.sourceforge.net>
  Copyright (c) 2009-2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Library General Public
  License as published by the Free Software Foundation; either
  version 2 of the License, or (at your option) any later version.

  This library 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
  Library General Public License for more details.

  You should have received a copy of the GNU Library General Public License
  along with this library; see the file COPYING.LIB.  If not, write to
  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  Boston, MA 02110-1301, USA.
*/
/**
  @file
  This file is part of the API for handling calendar data and provides
  static functions for formatting Incidence properties for various purposes.

  @brief
  Provides methods to format Incidence properties in various ways for display purposes.

  @author Cornelius Schumacher \<schumacher@kde.org\>
  @author Reinhold Kainhofer \<reinhold@kainhofer.com\>
  @author Allen Winter \<allen@kdab.com\>
*/
#include "stringify.h"

#include <kcalcore/exceptions.h>
using namespace KCalCore;

#include <KLocale>
#include <KGlobal>
#include <KSystemTimeZone>

using namespace KCalUtils;
using namespace Stringify;

QString Stringify::incidenceType( Incidence::IncidenceType type )
{
  switch( type ) {
  case Incidence::TypeEvent:
    return i18nc( "@item incidence type is event", "event" );
  case Incidence::TypeTodo:
    return i18nc( "@item incidence type is to-do/task", "to-do" );
  case Incidence::TypeJournal:
    return i18nc( "@item incidence type is journal", "journal" );
  case Incidence::TypeFreeBusy:
    return i18nc( "@item incidence type is freebusy", "free/busy" );
  default:
    return QString();
  }
}

QString Stringify::todoCompletedDateTime( const Todo::Ptr &todo,
                                          bool shortfmt )
{
  return KGlobal::locale()->formatDateTime( todo->completed().dateTime(),
                                            ( shortfmt ? KLocale::ShortDate :
                                                         KLocale::LongDate ) );
}

QString Stringify::incidenceSecrecy( Incidence::Secrecy secrecy )
{
  switch ( secrecy ) {
  case Incidence::SecrecyPublic:
    return i18nc( "@item incidence access if for everyone", "Public" );
  case Incidence::SecrecyPrivate:
    return i18nc( "@item incidence access is by owner only", "Private" );
  case Incidence::SecrecyConfidential:
    return i18nc( "@item incidence access is by owner and a controlled group", "Confidential" );
  default: // to make compiler happy
    return QString();
  }
}

QStringList Stringify::incidenceSecrecyList()
{
  QStringList list;
  list << incidenceSecrecy( Incidence::SecrecyPublic );
  list << incidenceSecrecy( Incidence::SecrecyPrivate );
  list << incidenceSecrecy( Incidence::SecrecyConfidential );

  return list;
}

QString Stringify::incidenceStatus( Incidence::Status status )
{
  switch ( status ) {
  case Incidence::StatusTentative:
    return i18nc( "@item event is tentative", "Tentative" );
  case Incidence::StatusConfirmed:
    return i18nc( "@item event is definite", "Confirmed" );
  case Incidence::StatusCompleted:
    return i18nc( "@item to-do is complete", "Completed" );
  case Incidence::StatusNeedsAction:
    return i18nc( "@item to-do needs action", "Needs-Action" );
  case Incidence::StatusCanceled:
    return i18nc( "@item event orto-do is canceled; journal is removed", "Canceled" );
  case Incidence::StatusInProcess:
    return i18nc( "@item to-do is in process", "In-Process" );
  case Incidence::StatusDraft:
    return i18nc( "@item journal is in draft form", "Draft" );
  case Incidence::StatusFinal:
    return i18nc( "@item journal is in final form", "Final" );
  case Incidence::StatusX:
  case Incidence::StatusNone:
  default:
    return QString();
  }
}

QString Stringify::incidenceStatus( const Incidence::Ptr &incidence )
{
  if ( incidence->status() == Incidence::StatusX ) {
    return incidence->customStatus();
  } else {
    return incidenceStatus( incidence->status() );
  }
}

QString Stringify::attendeeRole( Attendee::Role role )
{
  switch ( role ) {
  case Attendee::Chair:
    return i18nc( "@item chairperson", "Chair" );
    break;
  default:
  case Attendee::ReqParticipant:
    return i18nc( "@item participation is required", "Participant" );
    break;
  case Attendee::OptParticipant:
    return i18nc( "@item participation is optional", "Optional Participant" );
    break;
  case Attendee::NonParticipant:
    return i18nc( "@item non-participant copied for information", "Observer" );
    break;
  }
}

QStringList Stringify::attendeeRoleList()
{
  QStringList list;
  list << attendeeRole( Attendee::ReqParticipant );
  list << attendeeRole( Attendee::OptParticipant );
  list << attendeeRole( Attendee::NonParticipant );
  list << attendeeRole( Attendee::Chair );

  return list;
}

QString Stringify::attendeeStatus( Attendee::PartStat status )
{
  switch ( status ) {
  default:
  case Attendee::NeedsAction:
    return i18nc( "@item event, to-do or journal needs action", "Needs Action" );
    break;
  case Attendee::Accepted:
    return i18nc( "@item event, to-do or journal accepted", "Accepted" );
    break;
  case Attendee::Declined:
    return i18nc( "@item event, to-do or journal declined", "Declined" );
    break;
  case Attendee::Tentative:
    return i18nc( "@item event or to-do tentatively accepted", "Tentative" );
    break;
  case Attendee::Delegated:
    return i18nc( "@item event or to-do delegated", "Delegated" );
    break;
  case Attendee::Completed:
    return i18nc( "@item to-do completed", "Completed" );
    break;
  case Attendee::InProcess:
    return i18nc( "@item to-do in process of being completed", "In Process" );
    break;
  case Attendee::None:
    return i18nc( "@item event or to-do status unknown", "Unknown" );
    break;
  }
}

QStringList Stringify::attendeeStatusList()
{
  QStringList list;
  list << attendeeStatus( Attendee::NeedsAction );
  list << attendeeStatus( Attendee::Accepted );
  list << attendeeStatus( Attendee::Declined );
  list << attendeeStatus( Attendee::Tentative );
  list << attendeeStatus( Attendee::Delegated );
  list << attendeeStatus( Attendee::Completed );
  list << attendeeStatus( Attendee::InProcess );

  return list;
}

QString Stringify::formatTime( const KDateTime &dt, bool shortfmt, const KDateTime::Spec &spec )
{
  if ( spec.isValid() ) {

    QString timeZone;
    if ( spec.timeZone() != KSystemTimeZones::local() ) {
      timeZone = ' ' + spec.timeZone().name();
    }

    return KGlobal::locale()->formatTime( dt.toTimeSpec( spec ).time(), !shortfmt ) + timeZone;
  } else {
    return KGlobal::locale()->formatTime( dt.time(), !shortfmt );
  }
}

QString Stringify::formatDate( const KDateTime &dt, bool shortfmt, const KDateTime::Spec &spec )
{
  if ( spec.isValid() ) {

    QString timeZone;
    if ( spec.timeZone() != KSystemTimeZones::local() ) {
      timeZone = ' ' + spec.timeZone().name();
    }

    return
      KGlobal::locale()->formatDate( dt.toTimeSpec( spec ).date(),
                                     ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) ) +
      timeZone;
  } else {
    return
      KGlobal::locale()->formatDate( dt.date(),
                                     ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) );
  }
}

QString Stringify::formatDateTime( const KDateTime &dt, bool allDay,
                                   bool shortfmt, const KDateTime::Spec &spec )
{
  if ( allDay ) {
    return formatDate( dt, shortfmt, spec );
  }

  if ( spec.isValid() ) {
    QString timeZone;
    if ( spec.timeZone() != KSystemTimeZones::local() ) {
      timeZone = ' ' + spec.timeZone().name();
    }

    return KGlobal::locale()->formatDateTime(
      dt.toTimeSpec( spec ).dateTime(),
      ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) ) + timeZone;
  } else {
    return  KGlobal::locale()->formatDateTime(
      dt.dateTime(),
      ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) );
  }
}

QString Stringify::errorMessage( const Exception &exception )
{
  QString message = "";

  switch ( exception.code() ) {
  case Exception::LoadError:
    message = i18nc( "@item", "Load Error" );
    break;
  case Exception::SaveError:
    message = i18nc( "@item", "Save Error" );
    break;
  case Exception::ParseErrorIcal:
    message = i18nc( "@item", "Parse Error in libical" );
    break;
  case Exception::ParseErrorKcal:
    message = i18nc( "@item", "Parse Error in the kcalcore library" );
    break;
  case Exception::NoCalendar:
    message = i18nc( "@item", "No calendar component found." );
    break;
  case Exception::CalVersion1:
    message = i18nc( "@item", "Expected iCalendar, got vCalendar format" );
    break;
  case Exception::CalVersion2:
    message = i18nc( "@item", "iCalendar Version 2.0 detected." );
    break;
  case Exception::CalVersionUnknown:
    message = i18nc( "@item", "Expected iCalendar, got unknown format" );
    break;
  case Exception::Restriction:
    message = i18nc( "@item", "Restriction violation" );
    break;
  case Exception::NoWritableFound:
    message = i18nc( "@item", "No writable resource found" );
    break;
  case Exception::SaveErrorOpenFile:
    Q_ASSERT( exception.arguments().count() == 1 );
    message = i18nc( "@item", "Error saving to '%1'.", exception.arguments()[0] );
    break;
  case Exception::SaveErrorSaveFile:
    Q_ASSERT( exception.arguments().count() == 1 );
    message = i18nc( "@item", "Could not save '%1'", exception.arguments()[0] );
    break;
  case Exception::LibICalError:
    message = i18nc( "@item", "libical error" );
    break;
  case Exception::VersionPropertyMissing:
    message = i18nc( "@item", "No VERSION property found" );
    break;
  case Exception::ExpectedCalVersion2:
    message = i18nc( "@item", "Expected iCalendar, got vCalendar format" );
    break;
  case Exception::ExpectedCalVersion2Unknown:
    message = i18nc( "@item", "Expected iCalendar, got unknown format" );
    break;
  case Exception::ParseErrorNotIncidence:
    message = i18nc( "@item", "object is not a freebusy, event, todo or journal" );
    break;
  case Exception::ParseErrorEmptyMessage:
    message = i18nc( "@item", "messageText is empty, unable to parse into a ScheduleMessage" );
    break;
  case Exception::ParseErrorUnableToParse:
    message = i18nc( "@item", "icalparser is unable to parse messageText into a ScheduleMessage" );
    break;
  case Exception::ParseErrorMethodProperty:
    message = i18nc( "@item", "message does not contain ICAL_METHOD_PROPERTY" );
    break;
  case Exception::UserCancel:
    // no real error; the user canceled the operation
    break;

  }

  return message;
}

QString Stringify::scheduleMessageStatus( ScheduleMessage::Status status )
{
  switch( status ) {
  case ScheduleMessage::PublishNew:
    return i18nc( "@item this is a new scheduling message",
                  "New Scheduling Message" );
  case ScheduleMessage::PublishUpdate:
    return i18nc( "@item this is an update to an existing scheduling message",
                  "Updated Scheduling Message" );
  case ScheduleMessage::Obsolete:
    return i18nc( "@item obsolete status", "Obsolete" );
  case ScheduleMessage::RequestNew:
    return i18nc( "@item this is a request for a new scheduling message",
                  "New Scheduling Message Request" );
  case ScheduleMessage::RequestUpdate:
    return i18nc( "@item this is a request for an update to an existing scheduling message",
                  "Updated Scheduling Message Request" );
  default:
    return i18nc( "@item unknown status", "Unknown Status: %1", int( status ) );
  }
}

QString Stringify::secrecyName( Incidence::Secrecy secrecy )
{
  switch ( secrecy ) {
  case Incidence::SecrecyPublic:
    return i18nc( "@item incidence access if for everyone", "Public" );
  case Incidence::SecrecyPrivate:
    return i18nc( "@item incidence access is by owner only", "Private" );
  case Incidence::SecrecyConfidential:
    return i18nc( "@item incidence access is by owner and a controlled group", "Confidential" );
  default:
    return QString();  // to make compilers happy
  }
}

QStringList Stringify::secrecyList()
{
  QStringList list;
  list << secrecyName( Incidence::SecrecyPublic );
  list << secrecyName( Incidence::SecrecyPrivate );
  list << secrecyName( Incidence::SecrecyConfidential );

  return list;
}
