//*********************************************************************
//
//  NAV_UPGRADE.CMD - Command script to upgrade POI Data
//
//*********************************************************************

//! @li 2015/06/29 K. KOUEKA   EVO 7532 : ZAR Development (Folder #12943)
//! @li 2012/01/27 L. BARISSET EVO 6278 : Detect if file name is ZAR_POI, CARCH_POI or POI
//! @li 2011/12/15 L. BARISSET Def35219 : Prevent POI upgrade if MMIs are OFF
//! @li 2011/12/13 L. BARISSET Def38210 : Improve copy of POI during upgrade
//! @li 2009/12/02 P. CHAPELET Def27966 : Double display popup
//! @li 2009/11/27 P. CHAPELET Def27844 : Wrong message displayed for a radars upgrade
//!                            Def27977 : Impossible to upgrade with CD containing POI
//! @li 2009/02/11 P. CHAPELET Def25786 : Manage good popups at the end of upgrade


/*** GLOBAL DEFINES ****/

// Script Types
typedef int  STATUS;
typedef void DIR;
typedef int  BOOL;
typedef int  size_t;
typedef void FILE;
#define TRUE     (1)
#define FALSE    (0)
#define OK       (0)
#define ERROR    (-1)
#define NULL     (void*) 0
#define DELAY_5S (int) 2500


// Constants
#define MAX_DRIVE_NAME_LENGTH 10
#define MAX_FILENAME_LENGTH   50
#define MAX_PATH_LENGTH       100
#define MAX_QUESTION_LENGTH   100
#define MAX_ID_LENGTH         100
#define MAX_VERSION_LENGTH    95

#define MAX_COUNTRY_NAME_HDD  30
#define MAX_DATA_PROVIDER     30
#define MAX_DATE_LENGTH       30
#define STRING_CONTINENT_ID   "CONTINENT_ID"
#define STRING_CONTINENT_NAME "CONTINENT_NAME"
#define STRING_MEDIA_NAME     "MEDIA_NAME"
#define STRING_POI_PROVIDER   "POI_PROVIDER"
#define STRING_VERSION        "VERSION"
//#define MAPPE_PATH            "MAPPE/POI_USER"

#define UPG_DATA_DIR          "DATA/"
#define UPG_BASE1_DIR         "BASE1/"
#define UPG_BASE2_DIR         "BASE2/"


// Drive letters
#define DRIVE_CDROM "/D"
#define DRIVE_NAV   "/SDH"
#define DRIVE_USB   "/bd0"

// Key Files
#define KEY_ZAR_FILE_POI                  "ZAR_POI.BIN"
#define KEY_CARCH_FILE_POI                "CARCH_POI.BIN"
#define KEY_POI_FILE_POI                  "POI.BIN"


#define UPG_CD_NUMBER_LIMIT   8704

#define MMI_UPG_DISPLAY_ASK_MOTOR 1


/*** SOFTWARE UPGRADE DEFINES ***/
// Continents
typedef enum
{
  UNKNOWN_CONTINENT = 0,
  EUROPE,
  AUSTRALIA,
  NORTH_AMERICA,
  SOUTH_AMERICA,
  INDIA,
  CHINA
} t_continent;

typedef struct
{
  t_continent m_continent;
  char m_continent_name[MAX_COUNTRY_NAME_HDD];
  char m_cd_name[MAX_COUNTRY_NAME_HDD];
  char m_poi_provider[MAX_DATA_PROVIDER];
  char m_date[MAX_DATE_LENGTH];
}t_poi_content;

typedef struct
{
  char  m_pFileName[MAX_PATH_LENGTH];
  char  m_pTargetPath[MAX_PATH_LENGTH];
  int   m_iSize;
} t_NavUpgData;


/*** EXTERN FUNCTION DECLARATIONS ***/

// File operations
int        logMsg (char*,int,int,int,int,int,int);

// String operations
STATUS     strcpy (char* target, char* source);
STATUS     strcat (char* target, char* source);
int        strcmp (char* str1, char* str2);
int        strncmp (char* str1, char* str2, int n);
STATUS     strlen (char* str);
char*      strstr(char* str, char* substr);
FILE*      fopen(char * file, char * mode );
int        fclose(FILE * fp);



// MMI UPG Panel management
STATUS ClearScreen(void);
STATUS ShowNavigationBargraph(void);
STATUS StepBargraph(char *text, int index);
STATUS ShowNavigationExtendedQuestionScreen (int p_InfoIndex, char * p_Text, int * p_Answer);

// Others
unsigned long tickGet (void);
STATUS        taskDelay (int ticks);
int           atoi(char * p_str);
STATUS        UPGCDEject(void);
int           IsUpgCheatCodeActivated(void);
STATUS        SendMessageMMINavPOILoaded(void);
STATUS        GetMessageMMINavCIDLoaded (void);
STATUS        CompareToDBContinent(int p_cd_continent);
STATUS        CheckCRCFile( const char* p_file_name );
STATUS        GetInfValue( const char* p_file_name, char* p_field, char* p_result );
STATUS        InstalPOIs(char* p_path, char* p_bargraph_name);
STATUS        UPGStopGuidance (void);
BOOL          GetMMIStateActive(void);
STATUS        GetCDVersion(char* p_cdVersion);

/*** INTERN FUNCTION DECLARATION ***/
STATUS        ExtractPOIInfo(const char* p_filepath, t_poi_content* p_content);



/****************************** MAIN ******************************/

int main(int argc, char **argv)
{
  // Local variables for general purpose
  STATUS l_script_status = OK;
  char l_source_drive[MAX_DRIVE_NAME_LENGTH];
  char l_target_drive[MAX_DRIVE_NAME_LENGTH];
  char l_pCDVersion[MAX_VERSION_LENGTH];


  char l_path         [MAX_PATH_LENGTH];
  char l_path_to_send [MAX_PATH_LENGTH];
  static char l_key_file_name [3][MAX_FILENAME_LENGTH];

  int  l_bUpgRequired = FALSE;
  char l_pQuestionText[MAX_QUESTION_LENGTH];
  BOOL l_mmi_state_active = FALSE;
  int  i                  = 0;
  FILE* l_file            = NULL;
  int l_cd_number         = ERROR;

  t_poi_content l_poi_content;
  l_poi_content.m_continent = UNKNOWN_CONTINENT;
  l_poi_content.m_continent_name[0] = '\0';
  l_poi_content.m_cd_name[0] = '\0';
  l_poi_content.m_poi_provider[0] = '\0';
  l_poi_content.m_date[0] = '\0';

  /*** SCRIPT INITIALIZATION ***/

  logMsg("Script initialization +, Time = %ld\n",tickGet(),0,0,0,0,0);

  //Get current source drive
  if(argc != 3)
  {
    logMsg("Incorrect number of params\n",0,0,0,0,0,0);
    l_script_status = ERROR;
  }
  else
  {
    strcpy(l_source_drive,argv[1]);
    logMsg("Source drive is %s\n",l_source_drive,0,0,0,0,0);

    //Insert 3 differents key file
    strcpy (l_key_file_name[0], KEY_ZAR_FILE_POI);
    strcpy (l_key_file_name[1], KEY_CARCH_FILE_POI);
    strcpy (l_key_file_name[2], KEY_POI_FILE_POI);
  }

  //Get current target drive
  strcpy ( l_target_drive,DRIVE_NAV );

/////////////////////////////////////////////////////////////////////////////////

  // Get installed CD Version
  if (ERROR == GetCDVersion (l_pCDVersion))
  {
    logMsg ( "GetCDVersion error on DBBoot\n",0,0,0,0,0,0 );
    l_script_status = ERROR;
  }
  else
  {
    logMsg ("CD version is %s\n", (int)l_pCDVersion, 0, 0, 0, 0, 0);
    l_cd_number = atoi (l_pCDVersion);
    if (ERROR == l_cd_number)
    {
      logMsg ("GetCDVersion error on %s when converting via atoi call\n",
              (int)l_pCDVersion, 0, 0, 0, 0, 0);
      l_script_status = ERROR;
    }
    else
    {
      //Get the right key file name and put it in the path
      do
      {
        strcpy ( l_path, l_source_drive);
        strcat ( l_path, UPG_DATA_DIR );
        if (UPG_CD_NUMBER_LIMIT > l_cd_number)
        {
          strcat ( l_path, UPG_BASE1_DIR );
        }
        else
        {
          strcat ( l_path, UPG_BASE2_DIR );
        }
        strcat ( l_path, l_key_file_name[i]);
        logMsg ( "Path Tested (%s) \n", (int)l_path, 0, 0, 0, 0, 0 );

        l_file = fopen ( (char*)l_path,"r");
        fclose(l_file);
        i++;
      }
      while((NULL == l_file) && (i < 3 ));
    }
  }

/////////////////////////////////////////////////////////////////////////////////

  if(OK == l_script_status)
  {
    logMsg("Target drive is %s\n",l_target_drive,0,0,0,0,0);
  }

  logMsg("Script initialization -, Time = %ld\n",tickGet(),0,0,0,0,0);

  /*** SCRIPT CHECK CRC ***/

  if(ERROR == CheckCRCFile(l_path))
  {
    logMsg ( "CheckCRCFile (%s) Error!!!\n", (int)l_path, 0, 0, 0, 0, 0 );
    l_script_status = ERROR;
  }
  else
  {
    strcpy (l_path_to_send , l_path);
    logMsg ( "CheckCRCFile (%s) OK!!!\n", (int)l_path, 0, 0, 0, 0, 0 );
  }


  /*** VERSION CHECK ***/

  if ( OK == l_script_status )
  {
    logMsg("Version check +, Time = %ld\n",tickGet(),0,0,0,0,0);

    // Read the information file
    if(OK == ExtractPOIInfo (l_path, &l_poi_content))
    {
      if (ERROR == CompareToDBContinent((int)l_poi_content.m_continent))
      {
        logMsg ( "CompareToDBContinent failed continent : '%d'\n",
                  l_poi_content.m_continent,0,0,0,0,0 );
        l_script_status = ERROR;
      }
      else
      {
        logMsg ( "CompareToDBContinent OK\n",0,0,0,0,0,0 );
      }
    }
    else
    {
      logMsg ( "ExtractPOIInfo error on %s\n",l_path,0,0,0,0,0 );
      l_script_status = ERROR;
    }

    logMsg("Version check -, Time = %ld\n",tickGet(),0,0,0,0,0);
  }

  /*** ASK USER AGREEMENT ***/

  if ( ERROR != l_script_status )
  {
    strcpy ( l_pQuestionText, l_poi_content.m_cd_name);
    strcat ( l_pQuestionText, " " );
    strcat ( l_pQuestionText, l_poi_content.m_date);

    //Do not ask user agreement if drive is empty
    ShowNavigationExtendedQuestionScreen (MMI_UPG_DISPLAY_ASK_MOTOR, l_pQuestionText, &l_bUpgRequired );
  }

  /*** UPGRADE ***/

  logMsg("Upgrade +, Time = %ld\n",tickGet(),0,0,0,0,0);

  if ( ( OK == l_script_status ) && ( TRUE == l_bUpgRequired ) )
  {
    ShowNavigationBargraph();
    StepBargraph (l_pQuestionText, 0);
    taskDelay(100);

    if ( ERROR == InstalPOIs(l_path_to_send, l_pQuestionText))
    {
      logMsg("InstalPOIs error (%s)\n",(int)l_path_to_send,0,0,0,0,0);
      l_script_status = ERROR;
    }
  }

  logMsg("Upgrade -, Time = %ld\n",tickGet(),0,0,0,0,0);

  l_mmi_state_active = GetMMIStateActive();

  /*** TERMINATION ***/
  if ( (OK == l_script_status) && ( TRUE == l_bUpgRequired ))
  {
    //if the MIIs are closed stop the poi upgrade
    if(TRUE == l_mmi_state_active)
    {
      if(ERROR == SendMessageMMINavPOILoaded())
      {
        logMsg ( "SendMessageMMINavPOILoaded failed\n",0,0,0,0,0,0 );
        l_script_status = ERROR;
      }
      logMsg ("Waiting  for 'POILoaded'\n", 0, 0, 0, 0, 0, 0);
      GetMessageMMINavCIDLoaded();
      logMsg ("GetMessageMMINavCIDLoaded OK \n", 0, 0, 0, 0, 0, 0);
    }
    else
    {
      logMsg("SCRIPT ERROR MMI is OFF!!!\n",0,0,0,0,0,0);
      l_script_status = ERROR;
    }
  }

  if ( 0 == strcmp(l_source_drive, DRIVE_CDROM) )
  {
    if ( ERROR == UPGCDEject() )
    {
      logMsg ( "UPG Media Eject error\n",0,0,0,0,0,0 );
    }
  }

  if ( FALSE == l_bUpgRequired )
  {
    logMsg ( "UPGRADE CANCELED BY USER!\n",0,0,0,0,0,0 );
    taskDelay (DELAY_5S);
  }
  else
  {
    if ( OK == l_script_status)
    {
      logMsg("UPGRADE COMPLETE!\n",0,0,0,0,0,0);
    }
    else
    {
      logMsg("SCRIPT ERROR!\n",0,0,0,0,0,0);
      taskDelay (DELAY_5S);
    }
  }

  ClearScreen();
  taskDelay(100);

  return ( l_script_status );
}


/********************** INTERN FUNCTION DEFINITION **********************/

STATUS ExtractPOIInfo(const char* p_filepath, t_poi_content* p_content)
{
  STATUS l_status = OK;
  char l_dummy_value[MAX_ID_LENGTH];

  if(NULL == p_filepath || NULL == p_content)
  {
    logMsg("ExtractPOIInfo: bad parameter\n",0,0,0,0,0,0);
    return (ERROR);
  }

  /** CONTINENT_ID **/
  if(OK == GetInfValue( p_filepath, STRING_CONTINENT_ID, l_dummy_value ))
  {
    p_content->m_continent = (t_continent)atoi(l_dummy_value);
  }
  else
  {
    logMsg("ExtractPOIInfo: Can't find CONTINENT_ID:\n",0,0,0,0,0,0);
    l_status = ERROR;
  }

  /** CONTINENT_NAME **/
  if(OK == GetInfValue( p_filepath, STRING_CONTINENT_NAME, l_dummy_value))
  {
    strcpy (p_content->m_continent_name, l_dummy_value);
    p_content->m_continent_name[MAX_COUNTRY_NAME_HDD-1]='\0';
  }
  else
  {
    logMsg("ExtractPOIInfo: Can't find CONTINENT_NAME:\n",0,0,0,0,0,0);
    l_status = ERROR;
  }

  /** MEDIA_NAME **/
  if(OK == GetInfValue( p_filepath, STRING_MEDIA_NAME, l_dummy_value))
  {
    strcpy (p_content->m_cd_name, l_dummy_value);
    p_content->m_cd_name[MAX_COUNTRY_NAME_HDD-1]='\0';
  }
  else
  {
    logMsg("ExtractPOIInfo: Can't find CD_NAME:\n",0,0,0,0,0,0);
    l_status = ERROR;
  }

  /** POI_PROVIDER **/
  if(OK == GetInfValue( p_filepath, STRING_POI_PROVIDER, l_dummy_value ))
  {
    strcpy (p_content->m_poi_provider, l_dummy_value);
    p_content->m_poi_provider[MAX_DATA_PROVIDER-1]='\0';;
  }
  else
  {
    logMsg("ExtractPOIInfo: Can't find POI_PROVIDER:\n",0,0,0,0,0,0);
    l_status = ERROR;
  }

  /** VERSION **/
  if(OK == GetInfValue( p_filepath, STRING_VERSION, l_dummy_value ))
  {
    strcpy (p_content->m_date, l_dummy_value);
    p_content->m_date[MAX_DATE_LENGTH-1]='\0';
  }
  else
  {
    logMsg("ExtractPOIInfo: Can't find POI_VERSION:\n",0,0,0,0,0,0);
    l_status = ERROR;
  }

  return (l_status);
}

