// Created 2011 By Colin G http://www.diydrones.com/profile/ColinG
// Modified 2013 by Colin G for Ardustation Mega

#define COMMANDFIELDWIDTH 18
#define CMDVALCOUNT       6


PROGMEM const prog_char textCommands[] =
		  //123456789012345678
		   "Restart Mission\n"
	       "Request Parameters\n"
		   "Stop Data Stream\n"
	       "Re-request Stream\n"
	       "Set GCS Home\n"
		   "Reset UAV Home";//\n"
       //"Fly in a square";

PROGMEM const prog_char confirmReset_Index[] =
	//01234567890123456789
	 "  This will reset\n"
	 "    the mission\n"
	 "    Press OK to\n"
	 "      Confirm";

PROGMEM const prog_char confirmRequest_Params[] =
      //01234567890123456789
       " This will request\n"
       "  the parameters\n"
       "   Press OK to\n"
       "     Confirm";

PROGMEM const prog_char confirmStop_Stream[] =
      //01234567890123456789
       "   This will stop\n"
       "   the data stream\n"
       "    Press OK to\n"
       "      Confirm";

PROGMEM const prog_char confirmStart_Stream[] =
      //01234567890123456789
       " This will restart\n"
       "  the data stream\n"
       "   Press OK to\n"
       "     Confirm";

PROGMEM const prog_char confirmSet_GCSHome[] =
      //01234567890123456789
       "This will initialise\n"
       "  the GCS's Home\n"
       "position. Ensure the\n"
       "UAV is next to GCS";
       
PROGMEM const prog_char confirmReset_Home[] =
      //01234567890123456789
       "This will initialise\n"
       "the Aircraft's Home\n"
       "position. Ensure it\n"
       "is **on the GROUND**";
//  struct msg_command_upload {
//	uint8_t action;
//	uint16_t itemNumber;
//	uint16_t listLength;
//	uint8_t commandID;
//	uint8_t p1;
//	int32_t p2;
//	int32_t p3;
//	int32_t p4;

//////////////////////////////////////////////////////////////////////////////
// Commands page
////////////////////////////////////////////////////////////////////////////////

PageCommands::PageCommands()
{
	/// Copy the header and types to internal storage
	_textCommands = textCommands;

	// Set up the local LCD def
	_linecount = LCD_ROWS-2;
	_cmdLCD = gText(0, 16, LCD_COLUMNS, _linecount, SystemFont5x7);
}


uint8_t
PageCommands::_enter()
{     
	// Draw the header
	GLCD.CursorTo(0, 0);
	GLCD.SelectFont(Arial_bold_14);
	GLCD.Printf_P(PSTR("UAV Commands"));
	GLCD.SelectFont(System5x7);

	// Draw the contents
	_drawLocal();
}


uint8_t
PageCommands::_refresh_med()
{
  
}

uint8_t
PageCommands::_refresh_slow()
{
  
}

//void
//PageCommands::_update(void)
//{
//        // don't waste time redrawing if we have no changes to announce
//        if (!_updated)
//                return;
//                
//        // don't redraw too often
//        if ((millis() - _lastRedraw) < STATUS_UPDATE_INTERVAL)
//                return;
//          
//        // redraw the page
//        _render();
//        _updated = false;
//        _lastRedraw = millis();
//}


void
PageCommands::_drawLocal(void)
{
  uint8_t         c;
  uint8_t         i,j,k;
  uint8_t         row;
  const prog_char *str;
  str = _textCommands;
  
  _cmdLCD.ClearArea();
  row = 0;
  
  i=0;
  for(j=0;j<_stateFirstVal+_linecount;j++) { //Need to go from zero to read through the string
    if (j>=_stateFirstVal)
      _cmdLCD.CursorTo(1,j-_stateFirstVal);
      
    k=0;

    for (;;) {
      c = pgm_read_byte_near(_textCommands + i++);
      if (0 == c)
        break;
      if ('\n' == c)
        break;
      else {
        if (j>=_stateFirstVal && j<CMDVALCOUNT && k++<COMMANDFIELDWIDTH)
          _cmdLCD.write(c);
      }
    }
  }
        
  // redraw the "choosing" marker
  _paintMarker();
}

/// Draw the "choosing" marker
void
PageCommands::_paintMarker(void)
{
  if (_state > 0 && _state < 100) {
    _cmdLCD.CursorTo(0,_state-1 - _stateFirstVal);
    _cmdLCD.write('>');
  }
}

/// remove the "choosing" marker
void
PageCommands::_clearMarker(void)
{
  if (_state > 0 && _state < 200) {
    _cmdLCD.CursorTo(0,_state-1 - _stateFirstVal);
    _cmdLCD.write(' ');
  }
}

void
PageCommands::_commandConfirm(void)
{
  switch (_state-201) {
	case 0: // Reset waypoint to zero
		_commandConfirmMessage(confirmReset_Index);
		break;
	case 1: // Request all the parameters
		_commandConfirmMessage(confirmRequest_Params);
		break;
	case 2: // Stop data stream
		_commandConfirmMessage(confirmStop_Stream);
		break;
	case 3: // Restart data stream
		_commandConfirmMessage(confirmStart_Stream);
		break;
	case 4: // Set GCS Home
		_commandConfirmMessage(confirmSet_GCSHome);
		break;
	case 5: // Set UAV Home
		_commandConfirmMessage(confirmReset_Home);
		break;
  }
}

void
PageCommands::_commandConfirmMessage(const prog_char *str)
{
  uint8_t         c;
  uint8_t         row;
  
  _cmdLCD.ClearArea();
  row = 0;
  
  for (;;) {
    c = pgm_read_byte_near(str++);
    if (0 == c)
      break;
    if ('\n' == c) {
      _cmdLCD.CursorTo(0, ++row);
      continue;
    }
    // emit
    _cmdLCD.write(c);
  }
}

void
PageCommands::_commandSend(void)
{
	uint8_t i;
	mavlink_message_t msg;
  
//  struct BinComm::msg_command_upload command;
	switch (_state - 201)
	{
	case 0: // Reset waypoint index
//		mavlink_msg_waypoint_request_list_pack(0xFF, 0xFA, &msg, 1, 1);
		// Restart the mission by setting the current waypoint to waypoint 1
//		mavlink_msg_waypoint_set_current_pack(0xFF, 0xFA, &msg, 1, 1, 1);
		
                //mavlink_msg_waypoint_set_current_send(MAVLINK_COMM_1, 1, 1, 1);

//		comm.send(&msg);
		break;
	case 1: // Request parameters
          gcs3.param_request(0);
//		mavlink_msg_param_request_list_pack(0xFF, 0xFA, &msg, 1, 1);

//		mavlink_msg_param_request_list_send(MAVLINK_COMM_0, 1, 1);
//		mavlink_msg_param_request_list_send(MAVLINK_COMM_1, 1, 1);

//		comm.send(&msg);
		break;
	case 2: // Stop Stream
		//mavlink_msg_request_data_stream_pack(0xFF, 0xFA, &msg, 1, 1, MAV_DATA_STREAM_ALL, 0, 0);

//		mavlink_msg_request_data_stream_send(MAVLINK_COMM_1, 1, 1, MAV_DATA_STREAM_ALL, 0, 0);

//		comm.send(&msg);
		break;
	case 3: // Start Stream
                gcs3.data_stream_request();
		break;
	case 4: // GCS Home
//		gcsLat = mavGPS.lat;
//		gcsLon = mavGPS.lon;
//		gcsAlt = mavGPS.alt;
		break;
	case 5: // UAV Home
//		mavlink_msg_command_pack(0xFF, 0xFA, &msg, 1, 1, MAV_CMD_DO_SET_HOME, 0, 1, 0, 0, 0);
		// uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, uint8_t target_system, uint8_t target_component, uint16_t seq, uint8_t frame, uint8_t command, uint8_t current, uint8_t autocontinue, float param1, float param2, float param3, float param4, float x, float y, float z)
//		if (mavWptCount.count != 0) {
//  
////			mavlink_msg_waypoint_count_pack(0xFF, 0xFA, &msg, 1, 1, mavWptCount.count);
////			comm.send(&msg);
//
////			mavlink_msg_waypoint_pack(0xFF, 0xFA, &msg, 1, 1, 0, MAV_FRAME_GLOBAL, MAV_CMD_DO_SET_HOME, 0, 0, 1, 0, 0, 0, 0, 0, 0);
//
////			mavlink_msg_waypoint_pack(0xFF, 0xFA, &msg, 1, 1, 0, MAV_FRAME_GLOBAL, MAV_CMD_NAV_WAYPOINT, 1, 1, 0, 0, 0, 0, mavGPS.lat, mavGPS.lon, mavGPS.alt);
////			comm.send(&msg);
//
//			delay(50);
//
////        	mavlink_msg_waypoint_request_pack(0xFF, 0xFA, &msg, 1, 1, 0);
////        	comm.send(&msg);
//        
//		}
		break;
	}

}

uint8_t 
PageCommands::_interact(uint8_t buttonid)
{
  _clearMarker();
  
  switch (buttonid) {
  case B_UP:
          // Navigation
          if (_state == 0) {
            if (_stateFirstVal > 0) {
              _stateFirstVal --;
              _updated = true;
            }
          }
          // Picking
          else if (_state > 1 && _state < 100) {
            if (_state == (_stateFirstVal + 1)) {
              _stateFirstVal--;
              _updated = true;
            }
            _state--;
          }
          // Confirming
          else if (_state > 200)
            return 0;
          break;
  case B_DOWN:
          // Navigation
          if (_state == 0) {
            if (_stateFirstVal < CMDVALCOUNT-_linecount) {
              _stateFirstVal++;
              _updated = true;
            }
          }
          // Picking
          else if (_state > 0 && _state < CMDVALCOUNT) {
            if (_state == (_stateFirstVal + _linecount)) {
              _stateFirstVal++;
              _updated = true;
            }
            _state++;
          }
          // Confirming
          else if (_state > 200)
            return 0;
          break;
  case B_OK:
          // Enter picking mode
          if (_state == 0) {
            _state = _stateFirstVal + 1;
          }
          // Choose command
          else if(_state < 100) {
            // Update the state
            _state += 200;
            _commandConfirm();
            return 0;
          }
          // Confirming
          else if(_state > 200) {
            // Save the value
            _commandSend();
            _state = 0;
            _updated = true;
            _drawLocal(); // Redraw the main screen
            return 0; // Leave before we draw the marker again
          }
          break;
  case B_LEFT:
          // Navigation
          if (_state == 0)
            Pages::move(-1);
          else // Selection, ignore
            return 0;
          break;
  case B_RIGHT:
          // Navigation
          if (_state == 0)
            Pages::move(1);
          else // Selection, ignore
            return 0;
          break;
  case B_CANCEL:
          if (_state == 0) {
            Pages::move(0);
            return 0;         // avoid drawing the cursor
          }
          else {
            if (_state > 200)
              _drawLocal(); // Redraw the main screen
            _state = 0;
            _updated = true;
          }
          break;
  }
  _paintMarker();
}