// RAN - 2015-06-26 - Fixed the issue with the leading zeros in Zulu

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QDebug>
#include <QString>
#include <cstdlib>

#include <QMessageBox>
#include <QMap>
#include "functions.h"
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif


// =========================================================
// Sort Functions
// =========================================================

bool validateSorts(const QString &a, const QString &b, const QString &c) {
     return (a.length() * b.length() * c.length() > 0);
}


void mySortAlpha(QString &a, QString &b, QString &c) {
    if (a > b ) {
        if (c > a)      swap(b,c);
        else if (b > c) swap(a,b);
        else {
            QString tmp = a;
            a = b; b = c; c = tmp;
        }
    }
    else {
        if (a > c) {
            QString tmp = c;
            c = b;  b = a; a = tmp;
        }
        else if (b > c) swap(b,c);
        else {
            // they are already in order :-)
        }
    }
}

void mySortBeta(QString &a, QString &b, QString &c) {
    if (a > b ) {
        if (c > a)      swap(a,b);
        else if (b > c) swap(a,c);
        else {
            QString tmp = a;
            a = b; b = c; c = tmp;
        }
    }
    else {
        if (a > c) {
            QString tmp = c;
            c = b;  b = a; a = tmp;
        }
        else if (b > c) swap(b,c);
        else {
            // they are already in order :-)
        }
    }
}

void mySortGamma(QString &a, QString &b, QString &c) {
    if (a > b ) {
        if (c > a)      swap(a,b);
        else if (b > c) swap(a,c);
        else {
            QString tmp = a;
            a = c; c = b; b = tmp;
        }
    }
    else {
        if (a > c) {
            QString tmp = c;
            c = b;  b = a; a = tmp;
        }
        else if (b > c) swap(b,c);
        else {
            // they are already in order :-)
        }
    }
}

void mySortDelta(QString &a, QString &b, QString &c) {
    if (a < b ) {
        if (c < a)      swap(a,b);
        else if (b < c) swap(a,c);
        else {
            QString tmp = a;
            a = b; b = c; c = tmp;
        }
    }
    else {
        if (a > c) {
            QString tmp = c;
            c = b;  b = a; a = tmp;
        }
        else if (b > c) swap(b,c);
        else {
            // they are already in order :-)
        }
    }
}


//========================================================
// Functions for the dice roller
//========================================================

#include <iostream>
using namespace std;
void MainWindow::diceAlpha(){
    int total = diceFinal01 + diceFinal02 + 2;
    line[0]->setText(QString::number(total));
}

void MainWindow::diceBeta(){
    int total = diceFinal01 + diceFinal01 + 2;
    line[0]->setText(QString::number(total));
}

void MainWindow::diceGamma(){
    int total = diceFinal01 - diceFinal02;
    line[0]->setText(QString::number(total));
}

void MainWindow::diceDelta(){
    int total = diceFinal01 + diceFinal02;
    line[0]->setText(QString::number(total));
}

// =========================================================
// Rock Paper Scissor Functions
// =========================================================



int RPSAlpha(char p1, char p2) {
    p1 = toupper(p1);
    p2 = toupper(p2);
    if ( p1 == 'P' ) {
        if ( p2 == 'P' )    return 0;
        else if (p2 == 'R') return 1;
        else                return 2;
    }

    else if (p1 == 'R') {
        if ( p2 == 'R' )    return 0;
        else if (p2 == 'S') return 1;
        else                return 2;
    }

    else {
        if ( p2 == 'S' )    return 0;
        else if (p2 == 'P') return 1;
        else                return 2;
    }
}


int RPSBeta(char p1, char p2) {
    p1 = toupper(p1);
    p2 = toupper(p2);
    if ( p1 == 'P' ) {
        if ( p2 == 'S' )    return 0;
        else if (p2 == 'R') return 1;
        else                return 2;
    }
    else if (p1 == 'R') {
        if ( p2 == 'S' )    return 0;
        else if (p2 == 'P') return 1;
        else                return 2;
    }

    else {
        if ( p2 == 'S' )    return 0;
        else if (p2 == 'R') return 1;
        else                return 2;
    }
}



int RPSGamma(char p1, char p2) {
    p1 = toupper(p1);
    p2 = toupper(p2);
    if ( p1 == 'P' ) {
        if ( p2 == 'P' )    return 0;
        else if (p2 == 'S') return 1;
        else                return 2;
    }
    else if (p1 == 'R') {
        if ( p2 == 'R' )    return 0;
        else if (p2 == 'P') return 1;
        else                return 2;
    }
    else {
        if ( p2 == 'P' )    return 0;
        else if (p2 == 'S') return 1;
        else                return 2;
    }
}



int RPSDelta(char p1, char p2) {
    p1 = toupper(p1);
    p2 = toupper(p2);
    if ( p1 == 'P' ) {
        if ( p2 == 'P' )    return 0;
        else if (p2 == 'S') return 1;
        else                return 2;
    }
    else if (p1 == 'R') {
        if ( p2 == 'R' )    return 0;
        else if (p2 == 'P') return 1;
        else                return 2;
    }
    else {
        if ( p2 == 'P' )    return 0;
        else if (p2 == 'S') return 1;
        else                return 2;
    }
}

// =========================================================
// Check Words Functions
// =========================================================



QMap<int,QString> M;

///
/// \brief initCheckWMaps: initialize the values in the dictionary that is used throughout
///                        the check functions.
///

void initCheckWMaps() {

    M[1] = "one";       M[2] = "two";       M[3]  = "three";      M[4] = "four";
    M[5]  = "five";     M[6] = "six";
    M[7] = "seven";     M[8] = "eight";     M[9]  = "nine";       M[10] = "ten";
    M[11] = "eleven";   M[12] = "twelve";   M[13] = "thirteen";   M[14] = "fourteen";
    M[15] = "fifteen";  M[16] = "sixteen";  M[17] = "seventeen";  M[18] = "eighteen";
    M[19] = "nineteen";
    M[20] = "twenty";   M[30] = "thirty";   M[40] = "fourty";   M[50] = "fifty";
    M[60] = "sixty";    M[70] = "seventy";  M[80] = "eighty";   M[90] = "ninety";
}


///
/// \brief validateCheckQty: determines is entered text is a valid number in [0,999999999]
/// \param st text entered by the user
/// \param qty text converted to integer
/// \return true if the entered text is valid
///

bool validateCheckQty(QString st, unsigned int &qty) {
    int i = 0;
    for (i = 0; i < st.length() ; i++) {
        if (!st[i].isDigit()) return false;
    }

    if (i > 9) return false;

    qty = st.toInt();
    return true;
}

///
/// \brief wordForNumber: Given a number n in [0,999] returns the word equivalent
/// \param n: the number
/// \return a Qstring containing the number in words
///

QString wordForNumber(int n) {
    QString st;

    int tens = n % 100;
    if (tens == 0)
        st = "";
    else if (tens <= 20)
        st = M[n];
    else {
        st = M[10 * (tens/10)];
        if (tens % 10)
            st.append(" "  + M[tens % 10]);
    }

    n = n / 100;
    if (n) st.prepend(M[n % 10] + " hundred" + (st.length() > 0 ? " " : ""));

    return st;
}


///
/// \brief checkWAlpha: One of the functions to convert a number in [0,999999999] to words
/// \param n: the number
/// \return a Qstring containing the number in words
///

QString checkWAlpha(int n) {
    QString st;

    // the cents
    st = wordForNumber(n % 1000);

    // the thousands
    n = n / 1000;
    if (n % 1000) st.prepend( wordForNumber(n % 1000) + " thousand" +  (st.length() > 0 ? " " : ""));

    // the millions
    n = n / 1000;
    if (n % 1000) st.prepend( wordForNumber(n % 1000) + " million" +  (st.length() > 0 ? " " : ""));

    return st;
}

///
/// \brief checkWBeta: One of the functions to convert a number in [0,999999999] to words
/// \param n: the number
/// \return a Qstring containing the number in words
///

QString checkWBeta(int n) {
    QString st;

    st = wordForNumber(n % 1000);
    n = n / 1000;
    if (n % 1000) st.append( wordForNumber(n % 1000) + " thousand" +  (st.length() > 0 ? " " : ""));
    n = n / 1000;
    if (n % 1000) st.append( wordForNumber(n % 1000) + " million" +  (st.length() > 0 ? " " : ""));

    return st;
}

///
/// \brief checkWGamma: One of the functions to convert a number in [0,999999999] to words
/// \param n: the number
/// \return a Qstring containing the number in words
///

QString checkWGamma(int n) {
    QString st;

    st = wordForNumber(n % 10);
    n = n / 1000;
    if (n % 1000) st.append( wordForNumber(n % 10) + " thousand" +  (st.length() > 0 ? " " : ""));
    n = n / 1000;
    if (n % 1000) st.append( wordForNumber(n % 10) + " million" +  (st.length() > 0 ? " " : ""));

    return st;
}

///
/// \brief checkWDelta: One of the functions to convert a number in [0,999999999] to words
/// \param n: the number
/// \return a Qstring containing the number in words
///


QString checkWDelta(int n) {
    QString st;

    n /= 10;
    st = wordForNumber(n % 1000);
    n = n / 1000;
    if (n % 1000) st.prepend( wordForNumber(n % 1000) + " thousand" +  (st.length() > 0 ? " " : ""));
    n = n / 1000;
    if (n % 1000) st.prepend( wordForNumber(n % 1000) + " million" +  (st.length() > 0 ? " " : ""));

    return st;
}


// =========================================================
// Zulu Functions
// =========================================================


bool validZuluTime(const QString &time, const QString &zone, int &hours, int &minutes) {
    int i = 0;
    for (i = 0; i< time.size(); i++)
        if (!time[i].isDigit()) return false;

    if (i != 4) return false;
    hours   = time.mid(0,2).toInt();
    minutes = time.mid(2,2).toInt();

    if (hours < 0 || hours > 23 || minutes < 0 || minutes > 59)
        return false;

    if (zone.length() < 1 || zone[0] < 'A' ||
        zone[0] > 'Z'  || toupper(zone.toStdString()[0]) ==  'J')
        return false;

    return true;
}

//This is the correct one

QString zuluAlpha(int hours, int minutes, char zone) {
    int diff = 0;
    zone = toupper(zone);
    if (zone <= 'I')         diff = zone - 'A' + 1;
    else if (zone <= 'M')    diff = 10 + (zone - 'K');
    else if (zone <= 'Y')    diff = -(zone - 'N' + 1);
    else                     diff = 0;

    hours = (hours + (24 + diff) ) % 24;

    QString qstHours = QString::number(hours);
    if (qstHours.length() == 1) qstHours.prepend("0");

    QString qstMin = QString::number(minutes);
    if (qstMin.length() == 1) qstMin.prepend("0");

    return qstHours + qstMin;
}

QString zuluBeta(int hours, int minutes, char zone) {
    int diff = 0;

    if (zone <= 'I')         diff = zone - 'B' + 1;
    else if (zone <= 'M')    diff = 10 + (zone - 'M');
    else if (zone <= 'Y')    diff = -(zone - 'N');
    diff = 0;

    hours = (hours + (24 + diff) ) % 24;

    QString qstHours = QString::number(hours);
    if (qstHours.length() == 1) qstHours.prepend("0");

    QString qstMin = QString::number(minutes);
    if (qstMin.length() == 1) qstMin.prepend("0");

    return qstHours + qstMin;
}

QString zuluGamma(int hours, int minutes, char zone) {
    int diff = 0;

    if (zone <= 'I')          diff = zone - 'A' + 1;
    else if (zone <= 'M')     diff = 10 + (zone - 'M');
    else if (zone <= 'Y')     diff = -(zone - 'N');
    else                      diff = 0;

    hours = (hours + (24 + diff) ) % 24;

    QString qstHours = QString::number(hours);
    if (qstHours.length() == 1) qstHours.prepend("0");

    QString qstMin = QString::number(minutes);
    if (qstMin.length() == 1) qstMin.prepend("0");

    return qstHours + qstMin;
}

QString zuluDelta(int hours, int minutes, char zone) {
    int diff = 0;

    if (zone <= 'M')        diff = zone - 'B' + 1;
    else if (zone <= 'Y')   diff = -(zone - 'N');
    else                    diff = 0;

    hours = (hours + (24 - diff) ) % 24;

    QString qstHours = QString::number(hours);
    if (qstHours.length() == 1) qstHours.prepend("0");

    QString qstMin = QString::number(minutes);
    if (qstMin.length() == 1) qstMin.prepend("0");

    return qstHours + qstMin;
}



// =========================================================
// APFT Functions
// =========================================================


//This it the correct one

void MainWindow::APFTAlpha(){
    //For each one of these variables we apply the formula that they use
    //to set the points
    double sit_ups = qFloor(line[0]->text().toDouble() * 1.6 - 24.8);

    double push_ups = qFloor(line[1]->text().toInt() * 1.42);

    double running_time = qFloor((line[2]->text().left(2).append('.' + line[2]->text().right(2))).toDouble());
    double two_mile_run = qFloor((820 / 3) - ((40 * running_time) / 3));

    //Since the maximum of points that one can obtain
    //on each excercise type is 100, we restrict it
    if (sit_ups > 100){
        sit_ups = 100;
    }
    else if (sit_ups < 0){
        sit_ups = 0;
    }
    if (push_ups > 100){
        push_ups = 100;
    }
    else if (push_ups < 0){
        push_ups = 0;
    }
    if (two_mile_run > 100){
        two_mile_run = 100;
    }
    else if (two_mile_run < 0){
        two_mile_run = 0;
    }

    //Finally we set the outputs.
    line[3]->setText(QString::number(sit_ups));
    line[4]->setText(QString::number(push_ups));
    line[5]->setText(QString::number(two_mile_run));
    line[6]->setText(QString::number(push_ups + sit_ups + two_mile_run));
    if (push_ups >= 60 && sit_ups >= 60 && two_mile_run >= 60){
        label[7]->setText("PASS");
    }
    else{
        label[7]->setText("FAIL");
    }
}

//This one do not check if the number is greater than 100

void MainWindow::APFTBeta(){
    double sit_ups = qFloor(line[0]->text().toDouble() * 1.6 - 24.8);

    double push_ups = qFloor(line[1]->text().toInt() * 1.42);

    double running_time = qFloor((line[2]->text().left(2).append('.' + line[2]->text().right(2))).toDouble());
    double two_mile_run = qFloor((820 / 3) - ((40 * running_time) / 3));

    line[3]->setText(QString::number(sit_ups));
    line[4]->setText(QString::number(push_ups));
    line[5]->setText(QString::number(two_mile_run));
    line[6]->setText(QString::number(push_ups + sit_ups + two_mile_run));
    if (push_ups >= 60 && sit_ups >= 60 && two_mile_run >= 60){
        line[7]->setText("PASS");
    }
    else{
        line[7]->setText("FAIL");
    }
}

//This one switch the results

void MainWindow::APFTGamma(){
    double sit_ups = qFloor(line[0]->text().toDouble() * 1.6 - 24.8);
    double push_ups = qFloor(line[1]->text().toInt() * 1.42);
    double running_time = qFloor((line[2]->text().left(2).append('.' + line[2]->text().right(2))).toDouble());
    double two_mile_run = qFloor((820 / 3) - ((40 * running_time) / 3));

    if (sit_ups > 100){
        sit_ups = 100;
    }
    else if (sit_ups < 0){
        sit_ups = 0;
    }
    if (push_ups > 100){
        push_ups = 100;
    }
    else if (push_ups < 0){
        push_ups = 0;
    }
    if (two_mile_run > 100){
        two_mile_run = 100;
    }
    else if (two_mile_run < 0){
        two_mile_run = 0;
    }

    line[5]->setText(QString::number(sit_ups));
    line[3]->setText(QString::number(push_ups));
    line[4]->setText(QString::number(two_mile_run));
    line[6]->setText(QString::number(push_ups + sit_ups + two_mile_run));
    if (push_ups >= 60 && sit_ups >= 60 && two_mile_run >= 60){
        line[7]->setText("PASS");
    }
    else{
        line[7]->setText("FAIL");
    }
}

//This one do not sums the points but the quantities of each excercise

void MainWindow::APFTDelta(){
    double sit_ups = qFloor(line[0]->text().toDouble() * 1.6 - 24.8);
    double push_ups = qFloor(line[1]->text().toInt() * 1.42);
    double running_time = qFloor((line[2]->text().left(2).append('.'
                                   + line[2]->text().right(2))).toDouble());
    double two_mile_run = qFloor((820 / 3) - ((40 * running_time) / 3));

    if (sit_ups > 100){
        sit_ups = 100;
    }
    else if (sit_ups < 0){
        sit_ups = 0;
    }
    if (push_ups > 100){
        push_ups = 100;
    }
    else if (push_ups < 0){
        push_ups = 0;
    }
    if (two_mile_run > 100){
        two_mile_run = 100;
    }
    else if (two_mile_run < 0){
        two_mile_run = 0;
    }

    int sumaTo = line[0]->text().toInt() + line[1]->text().toInt() + running_time;
    line[3]->setText(QString::number(sit_ups));
    line[4]->setText(QString::number(push_ups));
    line[5]->setText(QString::number(two_mile_run));
    line[6]->setText(QString::number(sumaTo));
    if (push_ups >= 60 && sit_ups >= 60 && two_mile_run >= 60){
        line[7]->setText("PASS");
    }
    else{
        line[7]->setText("FAIL");
    }
}



