/*
 * $Id: calendar.c,v 1.1.1.1 2005/02/17 05:45:51 sundin Exp $
 *
 * Tag: $Name:  $
 *
 * See the file COPYRIGHT for copyright information
 *
 * $Log: calendar.c,v $
 * Revision 1.1.1.1  2005/02/17 05:45:51  sundin
 * initial import ver0.0.5
 *
 * Revision 1.2  2005/01/17 18:30:50  ksltuf
 * support for vdr 1.3.18 (readline)
 *
 * Revision 1.1.1.1  2005/01/17 18:06:31  ksltuf
 * PIM-Plugin 0.0.4
 *
 * Revision 1.4  2004/12/13 07:59:04  ksltuf
 * bugfix setup parsing; new option firstIsMonday
 *
 * Revision 1.3  2004/11/24 21:29:51  ksltuf
 * Changed order of include-Statements - VDR-includes come last
 * (problems with STL under gcc 2.95)
 *
 * Revision 1.2  2004/07/05 19:00:26  ksltuf
 * Added COPYRIGHT and cvs information
 *
 *
 */


#include <iostream>
#include <iomanip>
#include <string>

#include "calendar.h"
#include "pimSetup.h"

#include <vdr/config.h>
#include <vdr/tools.h>
#include <vdr/i18n.h>

int cCalendar::_rows = 6;  // rows: max weeks per month
int cCalendar::_cols = 7;  // cols: days per week

cCalendar::cCalendar()
{
  // calculate today's date
  
  time_t t = time(NULL);
  struct tm *now = localtime(&t);

  // default: display calendar for actual month
  
  _month = now->tm_mon + 1;
  _year  = now->tm_year + 1900;

  initData();
}


cCalendar::cCalendar(int month, int year) : _month(month), _year(year)
{
  initData();
}


cCalendar::~cCalendar()
{
}


void cCalendar::initData()
{
  // for convenience we calculate today's date each time this
  // method is called to make sure we (almost) never show yesterday's date
  // as today :-)
  
  time_t t = time(NULL);
  struct tm *now = localtime(&t);

  _today_d = now->tm_mday;
  _today_m = now->tm_mon + 1;
  _today_y = now->tm_year + 1900;

  _isValid = false;

  for(int i=0; i<_rows; ++i)
    {
      _data.push_back(std::vector<int>(_cols));
      for (int j=0; j<_cols; j++)
	_data[i][j] = 0;
    }
  calculateDays();
}


void cCalendar::increaseMonth()
{
  _month++;
  if (_month == 13)
    {
      _month = 1;
      _year++;
    }
  _isValid = false;
  initData();
}


void cCalendar::decreaseMonth()
{
  _month--;
  if (_month == 0)
    {
      _month = 12;
      _year--;
    }
  _isValid = false;
  initData();
}


void cCalendar::reset()
{
  time_t t = time(NULL);
  struct tm *now = localtime(&t);

  _month = now->tm_mon + 1;
  _year  = now->tm_year + 1900;

  _isValid = false;
  initData();
}


const char* cCalendar::getDayOfWeekAsText(const int day)
{
  switch (day)
  {
    case 1:
            return (globalSetup.firstIsMonday==1) ? tr("Mo") : tr("Su");
    case 2:
            return (globalSetup.firstIsMonday==1) ? tr("Tu") : tr("Mo");
    case 3:
            return (globalSetup.firstIsMonday==1) ? tr("We") : tr("Tu");
    case 4:
            return (globalSetup.firstIsMonday==1) ? tr("Th") : tr("We");
    case 5:
            return (globalSetup.firstIsMonday==1) ? tr("Fr") : tr("Th");
    case 6:
            return (globalSetup.firstIsMonday==1) ? tr("Sa") : tr("Fr");
    case 7:
            return (globalSetup.firstIsMonday==1) ? tr("Su") : tr("Sa");
    default:
	    return "Error";

  }
}

const char* cCalendar::getMonthAsText()
{
  switch (_month)
  {
    case 1:
	    return tr("January");
    case 2:
	    return tr("February");
    case 3:
	    return tr("March");
    case 4:
	    return tr("April");
    case 5:
	    return tr("May");
    case 6:
	    return tr("June");
    case 7:
	    return tr("July");
    case 8:
	    return tr("August");
    case 9:
	    return tr("September");
    case 10:
	    return tr("October");
    case 11:
	    return tr("November");
    case 12:
	    return tr("December");
    default:
	    return "Error";

  }
}


// calculate days for given month/year and fill in data[][]

void cCalendar::calculateDays()
{
  if (isValid())
    return;

  setInvalid();
  
  if ( _month < 0 || _month > 12 || _year < 1900 || _year > 2100)
    return;
  
  char* s = NULL;

  char *cmd = NULL;
  
  asprintf (&cmd, "%s %d %d", globalSetup.calCmd, _month, _year);

  FILE *p = popen(cmd, "r");

  if (p)
    {
      int row = 0;

#if VDRVERSNUM >= 10318
      cReadLine ReadLine;
      while ( (s = ReadLine.Read(p) ) != NULL )
#else
      while ( (s = readline(p) ) != NULL )
#endif
	{
	  ++row;

          // skip some rows; this assumes the output of cal-command looking
	  // something like
	  //                 Mai 2004
	  //           Mo Di Mi Do Fr Sa So
	  //                           1  2
	  //            3  4  5  6  7  8  9
	  //           10 11 12 13 14 15 16
	  //           17 18 19 20 21 22 23
	  //           24 25 26 27 28 29 30
	  //           31
	  //
	  if (row < 3)
	    continue;

	  for (unsigned int i = 0; i < 7 && i*3 < strlen(s); i++)
	    {
	      _data[row-3][i] = atoi(std::string(s+i*3, s+i*3+2).c_str());
	    }
	}

      setValid();

      pclose(p);
    }
  else
    {
      perror("popen");
      return;
    }

  free(cmd);

}



std::ostream& operator<< (std::ostream& os, const cCalendar& cal) 
{
  for (int i = 0; i < cCalendar::_rows; i++)
    {
      for (int j = 0; j < cCalendar::_cols; j++)
	os << std::setw(2) << cal[i][j] << " | ";
      os << std::endl;
    }
  return os;
}

