/*
 * Copyright (c) 2019 Clementine Computing LLC.
 *
 * This file is part of PopuFare.
 *
 * PopuFare is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * PopuFare is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with PopuFare.  If not, see <https://www.gnu.org/licenses/>.
 *
 */

#include "driver.h"

// This function searches the driver file and checks a driver, pin pair returning 0 on success
// or -1 on failure.
//
int driver_login(int drivernum, char *pinnum)
{
    FILE *f;
    char name[DRIVER_NAME_LEN]={0};
    char pin[64];
    char line[LINE_BUFFER_SIZE]={0};
    char *inc_line;
    struct message_record outgoing_msg;


    int drv;
    int retval;

    if(!drivernum || !pinnum) { return -1; }

    f=fopen(DRIVERS_FILE,"rb");       //open the driver file

    if(!f)
    {
        format_log_message(&outgoing_msg, LOGLEVEL_ERROR, "Cannot open %s\n", DRIVERS_FILE);
        send_message(hub_fd,&outgoing_msg);
        return -1;            //fail if we can't read it
    }

    while(!feof(f))         //while we haven't hit EOF
    {
        if(!fgets(line,sizeof(line)-1,f))   //read it line by line
            break;

        line[sizeof(line)-1] = '\0';          //terminating each line safely

        inc_line = line;

        while(1)        //and ignoring any leading whitespace
        {
            char c = *inc_line;

            if( (c == ' ') ||(c == '\t') ||(c == '\r') ||(c == '\n') )
            {
                inc_line++;
                continue;
            }

            break;
        }

        if( (inc_line[0] == '#') || (inc_line[0] == '\0'))                      //and ignoring blank/comment lines
            continue;

        name[0]='\0';
        pin[0]='\0';

        retval=sscanf(inc_line,"%d %63[0123456789] %63[^\r\n]",&drv,pin,name);  //parse the line format (drivernum pin_num drivername)

        if(retval >= 2)           //if we get at least a driver number and pin number
        {
            if(drv != drivernum)          //check to see if we've found a match
                continue;

            if(!strcmp(pinnum, pin))    //if the PIN matches
            {
                my_driver_status.logged_in_driver = drivernum;
                strncpy(my_driver_status.driver_name, name, DRIVER_NAME_LEN);
                my_driver_status.driver_name[DRIVER_NAME_LEN - 1] = '\0';
                my_driver_status.equip_num = get_equip_num();

                format_log_message(&outgoing_msg, LOGLEVEL_DEBUG, "Successful login for driver %d\n", drivernum);
                send_message(hub_fd,&outgoing_msg);

                update_driver_status |= 1;
                fclose(f);
                return 0;
            }
            else
            {
                format_log_message(&outgoing_msg, LOGLEVEL_DEBUG, "Failed login for driver %d\n", drivernum);
                send_message(hub_fd,&outgoing_msg);
                fclose(f);
                return -1;
            }
        }
    }

    format_log_message(&outgoing_msg, LOGLEVEL_DEBUG, "Failed login for unknown driver %d\n", drivernum);
    send_message(hub_fd,&outgoing_msg);
    fclose(f);
    return -1;
}

// Log a driver out and cancel any pending set paddle request
//
int driver_logout() {
  struct message_record outgoing_msg;

  if(my_driver_status.logged_in_driver) {
    format_log_message(&outgoing_msg, LOGLEVEL_DEBUG, "Driver logout for driver %d\n", my_driver_status.logged_in_driver);
    send_message(hub_fd,&outgoing_msg);
  }

  my_driver_status.logged_in_driver = 0;
  my_driver_status.driver_name[0] = '\0';
  paddle_req_timeout = 0;
  update_driver_status |= 1;
  return 0;
}

//--------------

int make_paddle_request(int paddle) {
  struct message_record outgoing_msg;

  paddle_req.result = 0;
  paddle_req.request = paddle;
  paddle_req_timeout = time(NULL) + PADDLE_REQ_TIMEOUT;

  prepare_message(&outgoing_msg, MAILBOX_SET_PADDLE, &paddle_req, sizeof(paddle_req));
  return send_message(hub_fd, &outgoing_msg);
}

int check_paddle_request() {
  char buf[LINE_BUFFER_SIZE];
  struct message_record outgoing_msg;

  if(paddle_req_timeout != 0) {

    if(paddle_req.request == paddle_req.result) {
      format_log_message(&outgoing_msg, LOGLEVEL_DEBUG, "Set Paddle %d\n", paddle_req.request);
      send_message(hub_fd, &outgoing_msg);
      paddle_req_timeout = 0;

      //setmenu(mt, paddle_ok_menu);
      snprintf(buf, LINE_BUFFER_SIZE, "paddle ok %i", paddle_req.result);
      ws_send(&g_mgr, buf);

      return 1;
    }
    else if( (paddle_req.result < 0) || (paddle_req_timeout < time(NULL)) ) {
      format_log_message(&outgoing_msg, LOGLEVEL_DEBUG, "Failed to set Paddle %d\n", paddle_req.request);
      send_message(hub_fd, &outgoing_msg);
      paddle_req.result = 0;
      paddle_req.request = 0;
      paddle_req_timeout = 0;

      //setmenu(mt, paddle_fail_menu);
      ws_send(&g_mgr, "paddle fail");

      return 1;
    }
  }

  return 0;
}

//--------------

void action_nextstop() {
  struct message_record outgoing_msg;
  prepare_message(&outgoing_msg, MAILBOX_NEXT_STOP, "", 0);
  send_message(hub_fd, &outgoing_msg);
}

void action_prevstop() {
  struct message_record outgoing_msg;
  prepare_message(&outgoing_msg, MAILBOX_PREV_STOP, "", 0);
  send_message(hub_fd, &outgoing_msg);
}

