// MainFrm.cpp : implementation of the CMainFrame class
//

#include "stdafx.h"
#include "Taxi4u.h"
#include "MainFrm.h"
#include "GPRMCData.h"
#include "Location.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#ifdef QA_RELEASE
#define WATCHDOG_TIMEOUT_VALUE    180
#else
#define WATCHDOG_TIMEOUT_VALUE    30
#endif

CScheduler*    g_pSchedule      =NULL;
CButtonWnd*    g_pButtonWnd    =NULL;
CLocationList*  g_pLocationList    =NULL;
CString g_sCurrentPlayingVideo    =L"";

HANDLE  g_hSystemListenThread    =NULL;
HANDLE  g_hDownloadThread      =NULL;
HANDLE  g_hNetworkThread      =NULL;
HANDLE  g_hLoadPlayListThread    =NULL;
HANDLE  g_hPrepareThread      =NULL;
HANDLE  g_hUploadLogFileThread    =NULL;
HANDLE  g_hAudioBrightCntrlThread  =NULL;
HANDLE  g_hExitSystemListenHandle  =CreateEvent(NULL,FALSE,FALSE,NULL);
HANDLE  g_hReadGPSDataHandle    =CreateEvent(NULL,FALSE,FALSE,NULL);
HANDLE  g_hExitNetworkHandle    =CreateEvent(NULL,FALSE,FALSE,NULL);

BOOL  g_bSystemListenExit      =TRUE;
BOOL  g_bNetworkThreadExit    =TRUE;
BOOL  g_bDownloadThreadExit    =TRUE;
BOOL  g_bLoadPlayListThreadExit  =TRUE;
BOOL  g_bExitDownloadThread    =TRUE;
BOOL  g_bPrepareThreadExit    =TRUE;
BOOL  g_bCustomerOn        =FALSE;
BOOL  g_bResetTriggerPlay      =FALSE;
BOOL  g_bUserChangedSetting    =FALSE;

Layout  g_CurrentVideoLayout    =LAYOUT_NUKNOW;

const DWORD dwAdornmentFlags = 0;  // exit button

extern BOOL IsNetPresent();
extern BOOL StartApp(const CString);
extern CConfig g_Config;      // The config file
extern CString g_CurrentPath;

CRITICAL_SECTION gcs_ReloadPlaylist;

/////////////////////////////////////////////////////////////////////////////
// CMainFrame

CMainFrame* CMainFrame::m_pMainFrame = NULL;

DWORD WINAPI SystemListenProc(PVOID pArg);
DWORD WINAPI NetworkProc(PVOID pArg);
DWORD WINAPI DownloadProc(PVOID pArg);
DWORD WINAPI LoadPlayListProc(PVOID pArg);
DWORD WINAPI PrepareProc(PVOID pArg);
DWORD WINAPI UploadLogFileProc(PVOID pArg);
DWORD WINAPI SetAudioBrightControlProc(PVOID pArg);

IMPLEMENT_DYNAMIC(CMainFrame, CFrameWnd)

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
  //{{AFX_MSG_MAP(CMainFrame)
  ON_WM_CREATE()
  //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMainFrame construction/destruction

CMainFrame::CMainFrame()
{
  //Auto run timer

  m_pRightAdWnd = 0;
  m_pAdBottomWnd = 0;
  m_pVideoWnd = 0;
  m_pButtonWnd = 0;
  m_pConsole = 0;
  //m_pForm1Wnd = 0;
  m_bSyncDateTime=TRUE;
  m_nGPSWaitingTime=1000;  // 5000
  m_pABC=NULL;

  InitializeCriticalSection(&gcs_ReloadPlaylist);
}

CMainFrame::~CMainFrame()
{
  DeleteCriticalSection(&gcs_ReloadPlaylist);
}

void CMainFrame::Release()
{
  CloseSerialPort();
  MYTRACE(L"Release Thread...");
  //Exit network listening thread
  SetEvent(g_hExitNetworkHandle);
  WaitForSingleObject(g_hNetworkThread,2000);

  //Exit download thread
  g_bExitDownloadThread=TRUE;
  WaitForSingleObject(g_hDownloadThread,2000);
  
  //Exit system listenhing thread
  SetEvent(g_hExitSystemListenHandle);
  WaitForSingleObject(g_hSystemListenThread,2000);

  MYTRACE(L"Release Resource...");
  if(m_pRightAdWnd)
  {
    delete m_pRightAdWnd;
    m_pRightAdWnd = 0;
  }
  if(m_pAdBottomWnd)
  {
    delete m_pAdBottomWnd;
    m_pAdBottomWnd = 0;
  }
  if(m_pVideoWnd)
  {
    delete m_pVideoWnd;
    m_pVideoWnd = 0;
  }
  if(m_pConsole)
  {
    delete m_pConsole;
    m_pConsole = 0;
  }
  /*
  if(m_pForm1Wnd)
  {
    delete m_pForm1Wnd;
    m_pForm1Wnd = 0;
  }
  */
  if(m_pButtonWnd)
  {
    delete m_pButtonWnd;
    m_pButtonWnd = 0;
  }
  if(g_pSchedule)
  {
    delete g_pSchedule;
    g_pSchedule=NULL;
  }

  if(g_pLocationList)
  {
    g_pLocationList->RemoveRecorder();
    g_pLocationList->Release();
    delete g_pLocationList;
  }
  MYTRACE_CONSOLE(NULL);  
  LOGDATA_DEINIT
}

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
  if( !CFrameWnd::PreCreateWindow(cs) )
    return FALSE;
  cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS, 
    NULL, HBRUSH(COLOR_BACKGROUND+1), NULL);
  return TRUE;
}

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
  if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
    return -1;

  // Create Right AD Window
  CRect adRect(VIDEOPART_WIDTH,0,SCREEN_WIDTH,VIDEOPART_HEIGHT);
  m_pRightAdWnd = new CRightAdWnd();
  if (!m_pRightAdWnd->Create(NULL, NULL, WS_CHILD|WS_VISIBLE,adRect,this, 11234, NULL))//WS_VISIBLE
  {
    MYTRACE(MT::LEVEL_ERROR,L"Failed to create right AD window");
    return -1;
  }
  
  // Create Bottom AD window
  m_pAdBottomWnd = new CBottomAdWnd();
  CRect bottomAdRect(0,VIDEOPART_HEIGHT,VIDEOPART_WIDTH,SCREEN_HEIGHT);
  if (!m_pAdBottomWnd->Create(NULL, NULL, WS_CHILD|WS_VISIBLE,bottomAdRect,this, 11235, NULL))
  {
    MYTRACE(MT::LEVEL_ERROR,L"Failed to create bottom AD window");
    return -1;
  }  

  // Create Video Window  
  m_pVideoWnd = new CVideoWnd(this->m_hWnd,m_pRightAdWnd,m_pAdBottomWnd);

  // Create Control Button window  
  g_pButtonWnd = m_pButtonWnd = new CButtonWnd();
  CRect btnRect(VIDEOPART_WIDTH,VIDEOPART_HEIGHT,SCREEN_WIDTH,SCREEN_HEIGHT);
  if (!m_pButtonWnd->Create(NULL, NULL, WS_CHILD|WS_VISIBLE,btnRect,this, 11237, NULL))
  {
    MYTRACE(MT::LEVEL_ERROR,L"Failed to create button window");
    return -1;
  }
  
  m_pMainFrame = this;
    
  #ifdef QA_RELEASE
  m_pConsole = new CConsole();
  m_pConsole->Create(IDD_DLGDEBUG,this);
  #endif
  /*
  m_pForm1Wnd = new CDialog_Form1();
  m_pForm1Wnd->Create(IDD_DIALOG_F1,this);
  */
  return 0;
}

void CMainFrame::OnInit()
{    
  //Initialize Serial Port
  m_nBaudrate=4800;
  m_nPortNum=2;
  InitSerialPort();

  //Open Serial Port to Get GPS Data  
  OpenSerialPort();
  
  //Create schedule
  g_pSchedule=new CScheduler(this->m_hWnd);

  //Update playlist
  PostMessage(WM_PLAYLIST_CHANGED,0,0);
  m_pAdBottomWnd->UpdateWindow();

  //Initialize WIFI Profile
  OnCreateWiFiProfile();

  //Start Player
  m_pVideoWnd->StartPlayer();

  //Start System Listening
  PostMessage(WM_CREATE_SYSTEMLISTEN,0,0);

  //Upload Log Files and Delete
  PostMessage(WM_UPLOAD_LOGFILES,0,0);
}

/////////////////////////////////////////////////////////////////////////////
// CMainFrame diagnostics

#ifdef _DEBUG
void CMainFrame::AssertValid() const
{
  CFrameWnd::AssertValid();
}

void CMainFrame::Dump(CDumpContext& dc) const
{
  CFrameWnd::Dump(dc);
}

#endif //_DEBUG

void CMainFrame::OnCreateWiFiProfile()
{  
  for(int i=0;i<g_Config.m_WiFi.GetSize();i++)
  {
    CProfile* profile = g_Config.m_WiFi.GetAt(i);
    if(profile->m_SSID.GetLength() > SSID_LEN)
    {
      MYTRACE(L"The SSID is not valid %s",profile->m_SSID);
      continue;
    }
    if(profile->m_Key.GetLength() > MAX_WPA_PSK_KEY_LENGTH)
    {
      MYTRACE(MT::LEVEL_ERROR,L"The Key is not valid %s",profile->m_Key);
      continue;
    }
    WiFiAuthCmdRequest wifi;
    memset(&wifi,0x00,sizeof (WiFiAuthCmdRequest));
    wcscpy(wifi.m_SSID,profile->m_SSID.GetBuffer(0));
    wifi.m_NetworkType = (WirelessNetworkType)profile->NetworkType;
    wifi.m_SecurityType = (SecurityType)profile->SecurityType;
    wifi.m_EncType =(EncryptionType)profile->EncType;

    WideCharToMultiByte(CP_ACP, 0, (LPCWSTR) profile->m_Key.GetBuffer(0), -1, wifi.szKey, sizeof(wifi.szKey), NULL, NULL);
    wifi.m_isHidden = FALSE;
    wifi.m_isLock = FALSE;
    wifi.ulWEPKeyIndex = 0;
    if(WiFiNetworkProfileCreate(&wifi))
    {
      MYTRACE(L"Create WIFI profile :%s",profile->m_SSID);
    }
    else
    {
      MYTRACE(MT::LEVEL_ERROR,L"Failed to create wifi profile :%s",profile->m_SSID);
    }
  }
}

void CMainFrame::ShowLayout(Layout layout)
{
  /*
  //Just adjust the layout, no need to control the playback
  if(g_CurrentVideoLayout==layout)
    return;  
  */
  
  if(g_CurrentVideoLayout==LAYOUT_FULLSCREEN)
    MediaPlayerControl(CMD_ORGSCREEN);

  g_CurrentVideoLayout=layout;

  switch(layout)
  {
    case LAYOUT_FULLSCREEN:
      MYTRACE(L"Adjust Layout... Set to CMD_FULLSCREEN");
      MediaPlayerControl(CMD_FULLSCREEN);
      m_pRightAdWnd->ShowWindow(SW_HIDE);
      m_pAdBottomWnd->ShowWindow(SW_HIDE);
      m_pButtonWnd->ShowWindow(SW_HIDE);
      m_pButtonWnd->UpdateWindow();
      break;
    case LAYOUT_640_384:
      MYTRACE(L"Adjust Layout... Set to LAYOUT_640_384");    // 16:9
      MediaPlayerControl(CMD_SET640X384);
      m_pRightAdWnd->ShowWindow(SW_SHOW);
      m_pButtonWnd->ShowWindow(SW_SHOW);
      m_pAdBottomWnd->ShowWindow(SW_SHOW);
      m_pButtonWnd->SetActiveWindow();
      break;  
    case LAYOUT_640_480:
      MYTRACE(L"Adjust Layout... Set to LAYOUT_640_480");    // 4:3
      MediaPlayerControl(CMD_SET640X480);
      m_pRightAdWnd->ShowWindow(SW_SHOW);
      m_pButtonWnd->ShowWindow(SW_SHOW);
      m_pAdBottomWnd->ShowWindow(SW_HIDE);
      m_pButtonWnd->SetActiveWindow();
      break;
    default:
      break;
  }
}

BOOL bTurn = FALSE;
LRESULT CMainFrame::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
{
  switch(message)
  {
    case WM_CLOSE:
    case WM_DESTROY:
    case WM_QUIT:
      Release();
      break;
    case WM_INIT:
      OnInit();
      break;
    case WM_SYSTEMDATE_CHANGED:
      OnSystemDateChange();
      break;
    case WM_CREATE_SYSTEMLISTEN:
      OnCreateSystemListen();
      break;
    case WM_CUSTOMER_CHANGED:
      OnCustomerChanged(wParam);
      break;
    case WM_SHOW_FORM:
      OnShowForm(wParam);
      break;
    case WM_NETWORK_CHANGED:    
      OnNetworkChanged(wParam);
      break;
    case WM_ACCPING_CHANGED:
      OnAccPingChanged(wParam);
      break;
    case WM_POWER_OFF:
      OnPowerOff();
    case WM_DOWNLOAD_FINISHED:
      OnDownloadFinished(wParam);
      break;
    case WM_GSML_PLAY_FINISHED:
      OnPlayVideoFinished();
      break;
    case WM_VIDEO_PLAYNEXT:
      OnPlayNextVideo((CVideoItem*)wParam);
      break;
    case WM_WACTHDOG_REST:
      DeviceControl(CMD_WATCHDOG_TIMER_RESET,0);
      break;
    case WM_PLAYLIST_CHANGED:
      OnPlayListChanged();
      break;
    case WM_PLAYLIST_LOADED:
      OnPlayListLoaded();
      break;
    case WM_UPLOAD_LOGFILES:
      OnUploadLogFiles();
      break;
    case WM_CONTINUE_PLAYING:
      OnContinuePlaying();
      break;
    case WM_STARTPLAYING:
      OnStartPlaying();
      break;
    case WM_GSML_PLAYER_PENUP:
      OnAudioBrightnessControl();
      break;
    case WM_GSML_PLAYER_PENDOWN:
      if (!this->m_pABC && g_bCustomerOn && g_CurrentVideoLayout==LAYOUT_FULLSCREEN)
      {
        MediaPlayerControl(CMD_PAUSE);
      }
      break;
    default:
      break;  
  }  
  return CWnd::WindowProc(message, wParam, lParam);
}

void CMainFrame::OnCreateSystemListen()
{
  if(g_bSystemListenExit)
  {      
    ResetEvent(g_hExitSystemListenHandle);
    g_hSystemListenThread = CreateThread(NULL,0,SystemListenProc,this->m_hWnd,0,NULL);
    //SetThreadPriority(g_hSystemListenThread,THREAD_PRIORITY_BELOW_NORMAL);    
  }
}

void CMainFrame::OnAccPingChanged(BOOL bValue)
{
  if(bValue)
  {
    MYTRACE(L"ACC On");
    LOGDATA(LOG_TYPE_ACC_, L"ON");
  }
  else
  {
    MYTRACE(L"ACC Off");
    LOGDATA(LOG_TYPE_ACC_, L"OFF");
    #ifdef QA_RELEASE
    MYTRACE(L"MMS Shutdown.");
    //::DestroyWindow(this->m_hWnd);
    exit(0);
    #endif
  }
}

void CMainFrame::OnPowerOff()
{
  MYTRACE(L"Power Off");
  SendMessage(WM_CLOSE,0,0);
  DeviceControl(CMD_DEVICE_POWER_OFF,2);
}

void CMainFrame::OnCustomerChanged(BOOL bCustomer)
{
  const  int nRebootNum = 50;
  static int nRebootTry = 0;

  if (bCustomer)
  {
    MYTRACE(L"Customer On!");
    LOGDATA(LOG_TYPE_FLAG, L"DOWN");
    g_bCustomerOn=TRUE;
    g_sCurrentPlayingVideo=L"";
    nRebootTry++;

    //Puts input focus back to main window
    this->EnableWindow();
    
    //Starts play video
    if(g_bPrepareThreadExit)
    {
      g_hPrepareThread = CreateThread(NULL,0,PrepareProc,this->m_hWnd,0,NULL);
    }
    
    //Turn off Console output on debug
    #ifdef QA_RELEASE    
    m_pConsole->Show(FALSE);    
    MediaPlayerControl(CMD_LAUNCHPLAYER);    
    #else
    DeviceControl(CMD_LCD_ON,0);
    #endif
    
    //OLD
    //Check time and apply business rule
    //From 7pm to 6am (night time), the brightness of LCD would be set to 2/5 automatically. 
    //From 6am to 7pm (daytime), it's set to 4/5.
    COleDateTime dt = COleDateTime::GetCurrentTime();
    int hour = dt.GetHour();
    int min = dt.GetMinute();
    
    //determine default sound/brightness level
    int nSetSoundLevel, nSetBrightnessLevel;
    if(hour >= 6 && hour <= g_Config.DimHour && min < g_Config.DimMinute)  //Day time
    {
      nSetSoundLevel = g_Config.m_SoundLevel.DefaultDayLevel;
      nSetBrightnessLevel = g_Config.m_BrightnessLevel.DefaultDayLevel;
    }
    else
    {
      nSetSoundLevel = g_Config.m_SoundLevel.DefaultNightLevel;
      nSetBrightnessLevel = g_Config.m_BrightnessLevel.DefaultNightLevel;
    }

    //determine brightness by time slot level
    if (hour > g_Config.m_BrightnessSlotLevel[3].m_Hour || (hour == g_Config.m_BrightnessSlotLevel[3].m_Hour && min > g_Config.m_BrightnessSlotLevel[3].m_Minute))
      nSetBrightnessLevel = g_Config.m_BrightnessSlotLevel[3].m_DefaultBrightnessLevel;
    else if (hour > g_Config.m_BrightnessSlotLevel[2].m_Hour || (hour == g_Config.m_BrightnessSlotLevel[2].m_Hour && min > g_Config.m_BrightnessSlotLevel[2].m_Minute))
      nSetBrightnessLevel = g_Config.m_BrightnessSlotLevel[2].m_DefaultBrightnessLevel;
    else if (hour > g_Config.m_BrightnessSlotLevel[1].m_Hour || (hour == g_Config.m_BrightnessSlotLevel[1].m_Hour && min > g_Config.m_BrightnessSlotLevel[1].m_Minute))
      nSetBrightnessLevel = g_Config.m_BrightnessSlotLevel[1].m_DefaultBrightnessLevel;
    else if (hour > g_Config.m_BrightnessSlotLevel[0].m_Hour || (hour == g_Config.m_BrightnessSlotLevel[0].m_Hour && min > g_Config.m_BrightnessSlotLevel[0].m_Minute))
      nSetBrightnessLevel = g_Config.m_BrightnessSlotLevel[0].m_DefaultBrightnessLevel;

    //determine audio by time slot level
    if (hour > g_Config.m_AudioSlotLevel[3].m_Hour || (hour == g_Config.m_AudioSlotLevel[3].m_Hour && min > g_Config.m_AudioSlotLevel[3].m_Minute))
      nSetSoundLevel = g_Config.m_AudioSlotLevel[3].m_DefaultAudioLevel;
    else if (hour > g_Config.m_AudioSlotLevel[2].m_Hour || (hour == g_Config.m_AudioSlotLevel[2].m_Hour && min > g_Config.m_AudioSlotLevel[2].m_Minute))
      nSetSoundLevel = g_Config.m_AudioSlotLevel[2].m_DefaultAudioLevel;
    else if (hour > g_Config.m_AudioSlotLevel[1].m_Hour || (hour == g_Config.m_AudioSlotLevel[1].m_Hour && min > g_Config.m_AudioSlotLevel[1].m_Minute))
      nSetSoundLevel = g_Config.m_AudioSlotLevel[1].m_DefaultAudioLevel;
    else if (hour > g_Config.m_AudioSlotLevel[0].m_Hour || (hour == g_Config.m_AudioSlotLevel[0].m_Hour && min > g_Config.m_AudioSlotLevel[0].m_Minute))
      nSetSoundLevel = g_Config.m_AudioSlotLevel[0].m_DefaultAudioLevel;

    //Set sound/brightness level    
    m_pButtonWnd->ResetLevel(nSetSoundLevel,nSetBrightnessLevel);

    //Open Serial Port
    OpenSerialPort();
  }
  else
  {    
    MYTRACE(L"Customer Off!");
    LOGDATA(LOG_TYPE_FLAG, L"UP");
    g_bCustomerOn=FALSE;
    g_bUserChangedSetting=FALSE;

    /*
    //Clear Old Zone Recorder
    g_pLocationList->RemoveRecorder();

    //Close Serial Port
    CloseSerialPort();
    */

    //Stop Video
    m_pVideoWnd->Stop();

    //Force close audio/bright setting control dialog
    if (m_pABC)
    {
      m_pABC->EndDialog(IDCANCEL);
      m_pABC=NULL;
    }

    //Turn on Console output on Debug
    #ifdef QA_RELEASE    
    MediaPlayerControl(CMD_CLOSEPLAYER);
    //g_CurrentVideoLayout=LAYOUT_640_384;
    m_pButtonWnd->ResetLevel(g_Config.m_SoundLevel.DefaultDayLevel,g_Config.m_BrightnessLevel.DefaultDayLevel);
    m_pConsole->Show(TRUE);
    CONSOLE(L"Log for QA version");
    #else
    DeviceControl(CMD_LCD_OFF,0);
    #endif

    this->SetForegroundWindow();
    /*
    //Reboot the MMS after X number of passengers, to clear memory
    if (nRebootTry >= nRebootNum)
    {
      MYTRACE(L"Reboot Num reached, rebooting MMS.");
      ::PostMessage(this->m_hWnd, WM_POWER_OFF,0,0);
      return;
    }
    */

    // reload play list every flag up and only when a triggered play has been set
    if (g_bResetTriggerPlay)
    {
      g_bResetTriggerPlay=FALSE;
      ::PostMessage(this->m_hWnd,WM_PLAYLIST_CHANGED,0,0);
    }

    //Create Network listening thread
    if(g_bNetworkThreadExit)
    {      
      ResetEvent(g_hExitNetworkHandle);
      g_hNetworkThread = CreateThread(NULL,0,NetworkProc,this->m_hWnd,0,NULL);
    }
  }
}

void CMainFrame::OnShowForm(BOOL bForm)
{
  //Stop Video
  m_pVideoWnd->Stop();
  MediaPlayerControl(CMD_CLOSEPLAYER);
  
  //m_pForm1Wnd->DoModal();
  //m_pForm1Wnd->EndDialog(IDCANCEL);

  /*
  //Puts input focus back to main window
  this->EnableWindow();
  this->UpdateWindow();
  this->ShowWindow(SW_SHOW);
  this->SetActiveWindow();
  this->SetFocus();
  this->BringToTop(SW_SHOW);
  this->BringWindowToTop();
  this->SetRedraw();
  this->UpdateData();
  this->RedrawWindow();
  this->ActivateFrame();
  this->SetWindowPos(&this->wndTopMost, 0,0,SCREEN_WIDTH, SCREEN_HEIGHT, NULL);
  this->SetWindowPos(&this->wndTopMost, 0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
  */
  this->SetForegroundWindow();

  //Starts play video
  if(g_bCustomerOn)
  {
    ::PostMessage(this->m_hWnd,WM_STARTPLAYING,0,0);
    //::PostMessage(this->m_hWnd,WM_CONTINUE_PLAYING,0,0);
  }  
  MediaPlayerControl(CMD_LAUNCHPLAYER);
}

void CMainFrame::OnNetworkChanged(BOOL bNetwork)
{
  if(bNetwork)
  {
    if(g_bDownloadThreadExit)
    {        
      g_bExitDownloadThread=FALSE;
      g_hDownloadThread = CreateThread(NULL,0,DownloadProc,this->m_hWnd,0,NULL);
    }
    LOGDATA(LOG_TYPE_WIFI, L"SUCC");
  }
  else
  {
    g_bExitDownloadThread=TRUE;
    LOGDATA(LOG_TYPE_WIFI, L"FAIL");
  }
}

void CMainFrame::OnAudioBrightnessControl()
{
  if (!this->m_pABC && g_bCustomerOn && g_CurrentVideoLayout==LAYOUT_FULLSCREEN)
  {
    Sleep(500);
    g_hAudioBrightCntrlThread = CreateThread(NULL,0,SetAudioBrightControlProc,this,0,NULL);
  }
}

void CMainFrame::OnDownloadFinished(BOOL bSuccess)
{  
  
}

void CMainFrame::OnPlayListLoaded()
{
  
}

void CMainFrame::OnPlayVideoFinished()
{
  //MYTRACE(L"Video Play Finished");
  m_pVideoWnd->m_bTriggeredPlay=FALSE;
  m_pVideoWnd->PlayNext();
}

void CMainFrame::OnPlayNextVideo(CVideoItem *pVideo)
{  
  ShowLayout(pVideo->m_Layout);  
}

void CMainFrame::OnPlayListChanged()
{
  if(g_bLoadPlayListThreadExit)
  {
    g_hLoadPlayListThread = CreateThread(NULL,0,LoadPlayListProc,this->m_hWnd,0,NULL);
  }
}

void CMainFrame::OnUploadLogFiles()
{
  if(!g_hUploadLogFileThread)
  {
    g_hUploadLogFileThread = CreateThread(NULL,0,UploadLogFileProc,this->m_hWnd,0,NULL);
  }
}

void CMainFrame::OnStartPlaying()
{
  //Load PlayList
  g_pSchedule->m_PlayList.m_SpecialVideoList.Reset();
  //g_pSchedule->m_PlayList.m_TriggerVideoList.Reset();    // CAN THIS FIX OLD BUG?????
  //g_pSchedule->m_PlayList.m_TriggerAdVideoList.Reset();
  m_pVideoWnd->PlayNext();
}

void CMainFrame::OnContinuePlaying()
{
  m_pVideoWnd->PlayNext();
}

void CMainFrame::InitSerialPort()
{
  m_SerialPort.m_nBaudRate=4800;
  m_SerialPort.set_data_callback(OnDataFromPort,this);
}

void CMainFrame::OpenSerialPort()
{
  if(!m_SerialPort.IsOpen())
  {    
    m_SerialPort.OpenPort(m_nPortNum);
  }
}

void CMainFrame::CloseSerialPort()
{
  if(m_SerialPort.IsOpen())
  {
    SetEvent(g_hReadGPSDataHandle);
    m_SerialPort.ClosePort();
  }
}

void CMainFrame::OnDataFromPort(void * data, DWORD nDataCount,void * context)
{
  CMainFrame *pFrm;
  pFrm=(CMainFrame *)context;
  char *buf;

  //char tt[5];
  buf=(char *)data;

  //Check GPS Data Begin With "$"
  if(pFrm->m_GPSData.GetLength()==0)
  {
    if(buf[0]!='$')
      return;
  }
  else if(buf[0]=='$')
  {
    pFrm->m_GPSData=_T("");
  }

  wchar_t * wText=new wchar_t[nDataCount];
  MultiByteToWideChar (CP_ACP, 0, buf, -1, wText, nDataCount);   
  pFrm->m_GPSData+=wText;
  delete[] wText;
  
  //Filter for GPGGA Data
  if(pFrm->m_GPSData.GetLength()==6)
  {
    if(pFrm->m_GPSData!=_T("$GPRMC"))
    {
      pFrm->m_GPSData=_T("");
      return;
    }
  }

  //Check GPS Data End With "\n"
  if(buf[0]!='\n')
    return;

  CString gpsData=pFrm->m_GPSData.Mid(0,pFrm->m_GPSData.GetLength()-2);
  pFrm->m_GPSData=_T("");
  
  //MYTRACE(L"Get GPS Data: %s",gpsData);
  //Parse GPRMC data
  CGPRMCData rmcData;

  if(!rmcData.CheckSum(gpsData))
    return;

  if(!rmcData.ParseData(gpsData))
    return;

  //MYTRACE(L"GPS Data: %s",gpsData);
  //Sync System DateTime
  if(pFrm->m_bSyncDateTime)
  {
    BOOL bDateChanged=FALSE;
    SYSTEMTIME sysTime;
    GetSystemTime(&sysTime);
    if(sysTime.wDay!=rmcData.m_UTCDataTime.wDay || sysTime.wMonth!=rmcData.m_UTCDataTime.wMonth 
      || sysTime.wYear!=rmcData.m_UTCDataTime.wYear)
    {
      bDateChanged=TRUE;
    }
    SetSystemTime(&rmcData.m_UTCDataTime);
    GetLocalTime(&sysTime);
    pFrm->m_bSyncDateTime=FALSE;
    MYTRACE(L"Sync System Time(ddmmyyyy hhmmss): %02d%02d%04d %02d%02d%02d"
      ,sysTime.wDay,sysTime.wMonth,sysTime.wYear
      ,sysTime.wHour,sysTime.wMinute,sysTime.wSecond);
    if(bDateChanged)
    {
      ::PostMessage(pFrm->m_hWnd,WM_SYSTEMDATE_CHANGED,0,0);
    }
    else if(!g_bCustomerOn)
    {
      //pFrm->CloseSerialPort();
      return;
    }
  }  
  WaitForSingleObject(g_hReadGPSDataHandle,pFrm->m_nGPSWaitingTime);
  ResetEvent(g_hReadGPSDataHandle);
}

void CMainFrame::OnSystemDateChange()
{
  MYTRACE(L"System Date Changed.");
  if(m_pLockWnd)
  {
    m_pLockWnd->EndDialog(IDOK);
  }
  else
  {
    SendMessage(WM_QUIT,0,0);
  }
  DeviceControl(CMD_WATCHDOG_SET_TIMEOUT,2);
  DeviceControl(CMD_WATCHDOG_ENABLE,0);
}

DWORD WINAPI SystemListenProc(PVOID pArg)  
{
  MYTRACE(L"Create System Listening Thread");
  g_bSystemListenExit=FALSE;
  HWND hwd=(HWND)pArg;
  int powerOffDelayTimer=g_Config.PowerTimer*1000*60;//1000*6;
  int waitingMs=2000;
  int nAccValue=-1;
  int nHirePinValue=-1;

  #ifndef QA_RELEASE
  DeviceControl(CMD_LCD_OFF,0);
  #endif
  
  DeviceControl(CMD_WATCHDOG_SET_TIMEOUT,WATCHDOG_TIMEOUT_VALUE);
  DeviceControl(CMD_WATCHDOG_ENABLE,0);
  
  while(1)
  {
    //Rest Watch Dog    
    ::PostMessage(hwd,WM_WACTHDOG_REST,0,0);

    //ACC checking
    int nNewAccValue = -1;
    if(DeviceGetState(CMD_12VINPUT_GET_ACC,&nNewAccValue) !=0 )
    {
      nNewAccValue=-1;
    }
    BOOL bAccOn=(nNewAccValue==0);
    if(nAccValue!=nNewAccValue)
    {
      ::PostMessage(hwd,WM_ACCPING_CHANGED,bAccOn,0);
      nAccValue=nNewAccValue;
      if(bAccOn)
      {
        powerOffDelayTimer=g_Config.PowerTimer*1000*60;
      }
    }
    if(!bAccOn)
    {
      powerOffDelayTimer-=waitingMs;
      if(powerOffDelayTimer<=0)
      {
        ::PostMessage(hwd,WM_POWER_OFF,0,0);
        break;
      }
    }

    //Customer checking
    int nNewHirePinValue = -1;
    if(bAccOn)
    {
      if(DeviceGetState(CMD_12VINPUT_GET_HIRED,&nNewHirePinValue) !=0 )
      {
        nNewHirePinValue=-1;
      }
    }
    else
    {
      nNewHirePinValue=1;
    }
    
    if(nHirePinValue!=nNewHirePinValue)
    {
      BOOL bCustomerOn=(nNewHirePinValue==0);      
      ::PostMessage(hwd,WM_CUSTOMER_CHANGED,bCustomerOn,0);
      nHirePinValue=nNewHirePinValue;
    }
    
    if(WaitForSingleObject(g_hSystemListenThread,waitingMs)==WAIT_OBJECT_0)
      break;    
  }
  g_bSystemListenExit=TRUE;
  MYTRACE(L"Exit System Listening Thread");
  return 1;
}

DWORD WINAPI NetworkProc(PVOID pArg)  
{  
  MYTRACE(L"Create Network listening thread");
  g_bNetworkThreadExit=FALSE;
  HWND hwd=(HWND)pArg;
  BOOL bConnected = FALSE;
  while(1)
  {
    if(IsNetPresent())
    {
      if(bConnected== FALSE)
      {        
        bConnected = TRUE;
        ::PostMessage(hwd,WM_NETWORK_CHANGED,bConnected,0);
      }
    }
    else
    {
      if(bConnected==TRUE)
      {
        bConnected = FALSE;
        ::PostMessage(hwd,WM_NETWORK_CHANGED,bConnected,0);
      }
    }
    
    if(WaitForSingleObject(g_hExitNetworkHandle,2000)==WAIT_OBJECT_0)
      break;
  }
  g_bNetworkThreadExit=TRUE;
  MYTRACE(L"Exit Network Listening Thread");
  return 1;
}

DWORD WINAPI DownloadProc(PVOID pArg)
{
  MYTRACE(L"Create Download Thread");
  g_bDownloadThreadExit=FALSE;
  HWND hwd=(HWND)pArg;
  g_pSchedule->Run();  
  ::PostMessage(hwd,WM_DOWNLOAD_FINISHED,0,0);
  g_bDownloadThreadExit=TRUE;
  //ResetEvent(g_hDownloadThread);
  MYTRACE(L"Exit Download Thread");
  return 1;
}

DWORD WINAPI LoadPlayListProc(PVOID pArg)
{
  g_bLoadPlayListThreadExit=FALSE;

  //MYTRACE(L"Create Load Play List Thread");

  HWND hwd=(HWND)pArg;
  //Wait for download thread exit
  if(!g_hDownloadThread)
  {
    if(WaitForSingleObject(g_hDownloadThread,1000*30)==WAIT_TIMEOUT)
    {
      ::PostMessage(hwd,WM_POWER_OFF,0,0);
      return 0;
    }
  }

  // only allow one thread to reload the playlist everytime
  EnterCriticalSection(&gcs_ReloadPlaylist);
  g_pSchedule->LoadPlayList();
  LeaveCriticalSection(&gcs_ReloadPlaylist);

  //g_pSchedule->m_PlayList.m_NormalVideoList.Reset();  //TODO
  g_bLoadPlayListThreadExit=TRUE;
  //ResetEvent(g_hLoadPlayListThread);
  //MYTRACE(L"Exit Load Play List Thread");
  return 1;
}

DWORD WINAPI PrepareProc(PVOID pArg)
{
  //MYTRACE(L"Create Prepare to Strat playing Thread");
  HWND hwd=(HWND)pArg;
  g_bPrepareThreadExit=FALSE;

  //Exit Network listen thread
  SetEvent(g_hExitNetworkHandle);
  if(!g_bNetworkThreadExit && WaitForSingleObject(g_hNetworkThread,1000*2)==WAIT_TIMEOUT)
  {
    MYTRACE(MT::LEVEL_ERROR,L"Waiting Exit Network Thread Time Out");
    g_bPrepareThreadExit=TRUE;
    ::PostMessage(hwd,WM_POWER_OFF,0,0);
    return 0;
  }
  
  //Exit Download thread
  g_bExitDownloadThread=TRUE;
  if(!g_bDownloadThreadExit && WaitForSingleObject(g_hDownloadThread,1000*25)==WAIT_TIMEOUT)
  {
    MYTRACE(MT::LEVEL_ERROR,L"Waiting Exit Download Thread Time Out");
    g_bPrepareThreadExit=TRUE;
    ::PostMessage(hwd,WM_POWER_OFF,0,0);
    return 0;
  }
  
  //Wait for loading play list completely
  if(!g_bLoadPlayListThreadExit && WaitForSingleObject(g_hLoadPlayListThread,1000*60)==WAIT_TIMEOUT)
  {
    MYTRACE(MT::LEVEL_ERROR,L"Waiting Exit Load Play List Thread Time Out");
    g_bPrepareThreadExit=TRUE;
    ::PostMessage(hwd,WM_POWER_OFF,0,0);
    return 0;
  }  
  g_bPrepareThreadExit=TRUE;

  //start playing
  if(g_bCustomerOn)
  {
    ::PostMessage(hwd,WM_STARTPLAYING,0,0);
  }
  return 1;
}

DWORD WINAPI UploadLogFileProc(PVOID pArg)
{
  CString sToday = L"";
  CString sFileName = L"";
  CString sFilePath = L"";
  WIN32_FIND_DATA lpFindFileData;

  COleDateTime dt = COleDateTime::GetCurrentTime();
  sToday.Format(_T("%d%02d%02d"), dt.GetYear(),dt.GetMonth(),dt.GetDay());
  
  HANDLE hFind = FindFirstFile(g_CurrentPath + L"*.log", &lpFindFileData);
  
  if (hFind == INVALID_HANDLE_VALUE)
    return -1;

  FTPInfo ftpinfo;
  FTP ftp;
  
  ftpinfo.lpszServerName  = L"cds.motionpower.com.hk";
  ftpinfo.lpszUserName  = L"cds";
  ftpinfo.lpszPassword  = L"spaceinet";
  ftpinfo.lpszDirectory  = L".";

  MYTRACE(L"*** Begin Upload ***");  
  do
  {
    if (!IsNetPresent())
      break;

    sFileName = lpFindFileData.cFileName;
    sFilePath = g_CurrentPath + sFileName;
    
    if (sFileName == "." || sFileName == ".." || sFileName.Find(sToday) != -1)
      continue;
        
    if (!(lpFindFileData.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
    {      
      ftpinfo.lpszLocalFile = sFilePath;
      ftpinfo.lpszRemoteFile = sFileName;
      
      if (ftp.UploadFile(ftpinfo))
      {
        MYTRACE(L"Uploaded Log File: %s", sFilePath);
        DeleteFile(sFilePath);
      }
    }
  }
  while (FindNextFile(hFind, &lpFindFileData));
  CloseHandle(hFind);
  MYTRACE(L"*** End Upload ***");

  return 0;
}

DWORD WINAPI SetAudioBrightControlProc(PVOID pArg)
{
  CMainFrame* pMain = (CMainFrame*) pArg;

  if (pMain && pMain->m_pButtonWnd)
  {
    CABControl abc(CButtonWnd::c_iCurrAudiLevel, CButtonWnd::c_iCurrBrtnLevel);    
    pMain->m_pABC=&abc;
    pMain->m_pButtonWnd->ResetLevel(g_Config.m_SoundLevel.DefaultDayLevel,g_Config.m_BrightnessLevel.DefaultDayLevel);    
    
    if (abc.DoModal() == IDOK && g_bCustomerOn)
    {
      pMain->m_pButtonWnd->ResetLevel(abc.GetAudioLevel(),abc.GetBrightLevel());
      Sleep(100);
      MediaPlayerControl(CMD_PLAY);
      Sleep(400);
      MediaPlayerControl(CMD_FULLSCREEN);
    }
    pMain->m_pABC=NULL;
  }
  return 0;
}