//writen by: E. van der Goot and Giorgio Cifani
//JRC, I-21020 Ispra, Italy
//date: 1996

//based on the original FORTRAN/SQL CGMS and WOFOST code
//produced by Tamme van der Wal, Kees van Diepen and Daniel van Kralingen
//Alterra, P.O. Box 6700 AA, Wageningen, The Netherlands

COleDateTime FindSowingDate(int nYear,
                                               SCropCalendar CC,
                                               SGridWeather GW[],
                                               SSoilPhysicalGroup SPG)
{

// Define dates from Crop Calendar
COleDateTime sowDate; // Sowing date
COleDateTime eSowDate(nYear, CC.nStartMonth1, CC.nStartMonthday1, 0, 0, 0);
// Earliest sowing day
COleDateTime lSowDate(nYear, CC.nStartMonth2, CC.nStartMonthday2, 0, 0, 0);
// Latest sowing day

// Check dates
if (eSowDate.GetStatus() == ::COleDateTime::invalid ||
        lSowDate.GetStatus() == ::COleDateTime::invalid ||
        lSowDate < eSowDate)
{
        sowDate.SetStatus(COleDateTime::invalid);
        return sowDate;
}

int nLenWorkPeriod = 0; // Length of workable period, should be 3 for sowing (sowing criterion)

// Define soil parameters
float fWExc = 2.0f;       // Excess amount of water in plow layer
float fCaprMx = 0.0f;     // Maximum upward flow into plow layer
float fEvSoil = 0.0f;       // Daily evaporation from bare soil surface
float fDSeep = 0.0f;      // Daily seepage

float fDelim;     // Minimum required soil moisture deficit in plow layer
                      // for occurrence of workable day (workability criterion)
float fSpac, fSpoc; // Topsoil seepage parameter for deep seedbed (potato)

// Upward flow as a function of negative values of WEXC, when
// topsoil is drier than field capacity
float ACaprFU[] = { -0.50f, 0.50f, 0.00f, 0.20f, 0.10f, 0.15f, 0.40f,0.10f, 1.00f, 0.05f };

SParameterValues CAPRFU[5];

// Set up array
for (int j = 0; j < 5; j ++)
     {
     CAPRFU[j].XValue = ACaprFU[j * 2];
     CAPRFU[j].YValue = ACaprFU[j * 2 + 1];
     }

// Get parameters from Soil Physical Group table
// REMEMBER: potato hard-coded...
if (CC.nCropNo == 7)
      {
      // Two seepage parameters for deep seedbed (potato)
      fSpac = SPG.fSpads;
      fSpoc = SPG.fSpods;

      fDelim = SPG.fDefLim;
      }
else
      {
      // Two seepage parameters for shallow seedbed (all other crops)
      fSpac = SPG.fSpass;
      fSpoc = SPG.fSposs;

      fDelim = 0.0f;
      }
 

// Find startdate, but don't go before jan 1st.
sowDate = ::COleDateTime(nYear, 1, 1, 0, 0, 0);
const COleDateTimeSpan tenDays(10.0);

if ((eSowDate - tenDays) > sowDate) sowDate = (eSowDate - tenDays);
const COleDateTimeSpan oneDay(1.0);

int nDay = sowDate.GetDayOfYear() - 1;

while (!((sowDate >= eSowDate && nLenWorkPeriod >= 3) || (sowDate ==lSowDate)))
        {
        // NOTE: convert units
        float fES0 = GW[nDay].fES0 / 10.0f;
 
        // Evaporation from soil surface
        if (fWExc >= 0.5f)
           {
           fCaprMx = 0.0f;
           fEvSoil = fES0;
           }
        else
           {
           // Maximum capillary rise to surface (cf. Ritchie)
           fCaprMx = AFGen(CAPRFU, 5, -fWExc);
           fEvSoil = min(fES0, (fCaprMx + GW[nDay].fRainfall));
           }

       fWExc = max(-1.0f, (fWExc + GW[nDay].fRainfall - fEvSoil));

       // Seepage
       if (fWExc > 0.0f)
          {
          fDSeep = min((fWExc * fSpac + fSpoc), fWExc);
          fWExc -= fDSeep;
          }

       // Criterion for workable day
       if (fWExc <= fDelim)
          nLenWorkPeriod++;
       else
          nLenWorkPeriod = 0;

       sowDate += oneDay;
       nDay ++;
       }

return sowDate;
}