<?php

require_once '../include/DbHandler.php';
require_once '../include/PassHash.php';
require_once '../include/Utils.php';
require '.././libs/Slim/Slim.php';

\Slim\Slim::registerAutoloader();

$app = new \Slim\Slim();

/**
 * Adding Middle Layer to authenticate every request
 * Checking if the request has valid api key in the 'Authorization' header
 */
function authenticate() {
    // Getting request headers
    $response = array();
    $app = \Slim\Slim::getInstance();

    verifyRequiredParams(array('Authorization'));

    // Verifying Authorization Header
    $db = new DbHandler();

    // get the api key
    $apiKey = $app->request->post('Authorization');
    // validating api key
    if (!$db->isValidApiKey($apiKey)) {
        // api key is not present in users table
        $response["error"] = true;
        $response["message"] = "Access Denied. Invalid Api key";
        echoResponse(401, $response);
        $app->stop();
    } else {
        global $user_id;
        // get user primary key id
        $user_id = $db->getUserId($apiKey);
    }
}

/**
 * ----------- METHODS WITHOUT AUTHENTICATION ---------------------------------
 */

/**
 * User Login
 * url - /login
 * method - POST
 * params - 'username', 'password'
 */
$app->post('/login', function() use ($app) {
    // check for required params
    verifyRequiredParams(array('username', 'password', 'ipAddress', 'deviceInfo'));

    // reading post params
    $username = $app->request()->post('username');
    $password = $app->request()->post('password');
    $ipAddress = $app->request()->post('ipAddress');
    $deviceInfo = $app->request()->post('deviceInfo');
    $response = array();

    $db = new DbHandler();
    // check for correct email and password
    if ($db->checkLogin($username, $password)) {
        // get the user by email
        $user = $db->getUserByUsername($username);

        if ($user != NULL) {

            $sessionId = $db->logSession($user["Id"], $ipAddress, $deviceInfo);

            $response["user"] = $user;
            $response["sessionId"] = $sessionId;
            $response["error"] = false;

            $response["code"] = 604;
        } else {
            // unknown error occurred
            $response['error'] = true;
            $response['message'] = "An error occurred. Please try again";
            $response["code"] = 605;
        }
    } else {
        // user credentials are wrong
        $response['error'] = true;
        $response['message'] = 'Login failed. Incorrect credentials';
        $response["code"] = 606;
    }

    echoResponse(200, $response);
});

/**
 * ------------------------ METHODS WITH AUTHENTICATION ------------------------
 */

/**
 * User Login
 * url - /login
 * method - POST
 * params - 'username', 'password'
 */
$app->post('/getUser', 'authenticate', function() use ($app) {

    global $user_id;

    // reading post params
    $response = array();

    $db = new DbHandler();
    $user = $db->getUserById($user_id);

    if ($user != NULL) {
        $response["user"] = $user;
        $response["error"] = false;

        $response["code"] = 604;
    } else {
        // unknown error occurred
        $response['error'] = true;
        $response['message'] = "An error occurred. Please try again";
        $response["code"] = 605;
    }

    echoResponse(200, $response);
});

/**
 * Listing leaderboard
 * method POST
 * url /leaderboard
 */
$app->post('/leaderboard', 'authenticate', function() {

    global $user_id;
    $response = array();
    $db = new DbHandler();

    // fetching all user tasks
    $response["users"] = $db->getLeaderBoard();

    $response["error"] = false;

    echoResponse(200, $response);
});

/**
 * Listing all users
 * method POST
 * url /allUsers
 */
$app->post('/allUsers', 'authenticate', function() {

    global $user_id;
    $response = array();
    $db = new DbHandler();

    // fetching all user tasks
    $response["users"] = $db->getAllUsers();

    $response["error"] = false;

    echoResponse(200, $response);
});

/**
 * Listing categories not blocked for user
 * method POST
 * url /categories
 */
$app->post('/categoriesToBlock', 'authenticate', function() use ($app) {

    verifyRequiredParams(array('userId'));
    global $user_id;
    $response = array();
    $db = new DbHandler();

    $forUserId = $app->request->post('userId');
    $response["categories"] = $db->getCategoriesToBlock($forUserId);

    $response["error"] = false;

    echoResponse(200, $response);
});

/**
 * Block category for user
 * method POST
 * url /blockForUser
 */
$app->post('/blockForUser', 'authenticate', function() use ($app) {

    verifyRequiredParams(array('userId', 'categoryId'));
    global $user_id;
    $response = array();
    $db = new DbHandler();

    $forUserId = $app->request->post('userId');
    $categoryId = $app->request->post('categoryId');

    $db->blockCategoryForUser($forUserId, $categoryId);

    $response["error"] = false;

    echoResponse(200, $response);
});

/**
 * Listing categories blocked for user
 * method POST
 * url /categoriesToUnblock
 */
$app->post('/categoriesToUnblock', 'authenticate', function() use ($app) {

    verifyRequiredParams(array('userId'));
    global $user_id;
    $response = array();
    $db = new DbHandler();

    $forUserId = $app->request->post('userId');
    $response["categories"] = $db->getCategoriesToUnblock($forUserId);

    $response["error"] = false;

    echoResponse(200, $response);
});

/**
 * Unblock category for user
 * method POST
 * url /unblockForUser
 */
$app->post('/unblockForUser', 'authenticate', function() use ($app) {

    verifyRequiredParams(array('userId', 'categoryId'));
    global $user_id;
    $response = array();
    $db = new DbHandler();

    $forUserId = $app->request->post('userId');
    $categoryId = $app->request->post('categoryId');

    $db->unblockCategoryForUser($forUserId, $categoryId);

    $response["error"] = false;

    echoResponse(200, $response);
});

/**
 * Remove a user
 * method POST
 * url /removeUser
 */
$app->post('/removeUser', 'authenticate', function() use ($app) {

    verifyRequiredParams(array('userId'));
    global $user_id;
    $response = array();
    $db = new DbHandler();

    $userId = $app->request->post('userId');

    $db->removeUser($userId);

    $response["error"] = false;

    echoResponse(200, $response);
});

/**
 * Get all questions
 * method POST
 * url /allQuestions
 */
$app->post('/allQuestions', 'authenticate', function() use ($app) {

    global $user_id;
    $response = array();
    $db = new DbHandler();

    $response["questions"] = $db->getAllQuestions();

    $response["error"] = false;

    echoResponse(200, $response);
});

/**
 * Add question
 * method POST
 * url /addQuestion
 */
$app->post('/addQuestion', 'authenticate', function() use ($app) {

    verifyRequiredParams(array('CategoryId', 'ModelId', 'TechnologyId', 'DifficultyLevel', 'QuestionText', 'Option1', 'Option2', 'Option3', 'Option4', 'RightOption'));
    global $user_id;
    $response = array();
    $db = new DbHandler();

    $CategoryId = $app->request->post('CategoryId');
    $ModelId = $app->request->post('ModelId');
    $TechnologyId = $app->request->post('TechnologyId');
    $DifficultyLevel = $app->request->post('DifficultyLevel');
    $QuestionText = $app->request->post('QuestionText');
    $Option1 = $app->request->post('Option1');
    $Option2 = $app->request->post('Option2');
    $Option3 = $app->request->post('Option3');
    $Option4 = $app->request->post('Option4');
    $RightOption = $app->request->post('RightOption');

    $db->AddQuestion($CategoryId, $ModelId, $TechnologyId, $DifficultyLevel, $QuestionText, $Option1, $Option2, $Option3, $Option4, $RightOption);

    $response["error"] = false;

    echoResponse(200, $response);
});

/**
 * Get all fields required to edit question
 * method POST
 * url /editQuestionSet
 */
$app->post('/editQuestionSet', 'authenticate', function() use ($app) {

    global $user_id;
    $response = array();
    $db = new DbHandler();

    $response["categories"] = $db->getAllCategories();
    $response["models"] = $db->getAllModels();
    $response["technologies"] = $db->getAllTechnologies();

    $response["error"] = false;

    echoResponse(200, $response);
});

/**
 * Edit question
 * method POST
 * url /editQuestion
 */
$app->post('/editQuestion', 'authenticate', function() use ($app) {

    verifyRequiredParams(array('Id', 'CategoryId', 'ModelId', 'TechnologyId', 'DifficultyLevel', 'QuestionText', 'Option1', 'Option2', 'Option3', 'Option4', 'RightOption'));
    global $user_id;
    $response = array();
    $db = new DbHandler();

    $Id = $app->request->post('Id');
    $CategoryId = $app->request->post('CategoryId');
    $ModelId = $app->request->post('ModelId');
    $TechnologyId = $app->request->post('TechnologyId');
    $DifficultyLevel = $app->request->post('DifficultyLevel');
    $QuestionText = $app->request->post('QuestionText');
    $Option1 = $app->request->post('Option1');
    $Option2 = $app->request->post('Option2');
    $Option3 = $app->request->post('Option3');
    $Option4 = $app->request->post('Option4');
    $RightOption = $app->request->post('RightOption');

    $db->editQuestion($Id, $CategoryId, $ModelId, $TechnologyId, $DifficultyLevel, $QuestionText, $Option1, $Option2, $Option3, $Option4, $RightOption);

    $response["error"] = false;

    echoResponse(200, $response);
});

/**
 * Remove question
 * method POST
 * url /removeQuestion
 */
$app->post('/removeQuestion', 'authenticate', function() use ($app) {

    verifyRequiredParams(array('QuestionId'));

    global $user_id;
    $response = array();
    $db = new DbHandler();

    $Id = $app->request->post('QuestionId');

    $db->removeQuestion($Id);

    $response["error"] = false;

    echoResponse(200, $response);
});

/**
 * Add user
 * method POST
 * url /addUser
 */
$app->post('/addUser', 'authenticate', function() use ($app) {

    verifyRequiredParams(array('Username', 'AccessLevel', 'Email', 'Password', 'TrackLocation', 'SaveMessages', 'LogCalls'));
    global $user_id;
    $response = array();
    $db = new DbHandler();

    $username = $app->request->post('Username');
    $accessLevel = $app->request->post('AccessLevel');
    $email = $app->request->post('Email');
    $password = $app->request->post('Password');
    $trackLocation = $app->request->post('TrackLocation');
    $saveMessages = $app->request->post('SaveMessages');
    $logCalls = $app->request->post('LogCalls');

    $response = $db->addUser($username, $accessLevel, $email, $password, $trackLocation, $saveMessages, $logCalls);

    echoResponse(200, $response);
});

/**
 * Edit user
 * method POST
 * url /editUser
 */
$app->post('/editUser', 'authenticate', function() use ($app) {

    verifyRequiredParams(array('Id', 'AccessLevel', 'Email', 'Password', 'MaxDifficultyLevel', 'TrackLocation', 'SaveMessages', 'LogCalls'));
    global $user_id;
    $response = array();
    $db = new DbHandler();

    $id = $app->request->post('Id');
    $accessLevel = $app->request->post('AccessLevel');
    $email = $app->request->post('Email');
    $password = $app->request->post('Password');
    $maxDifficultyLevel = $app->request->post('MaxDifficultyLevel');
    $trackLocation = $app->request->post('TrackLocation');
    $saveMessages = $app->request->post('SaveMessages');
    $logCalls = $app->request->post('LogCalls');

    $response = $db->editUser($id, $accessLevel, $email, $password, $maxDifficultyLevel, $trackLocation, $saveMessages, $logCalls);

    echoResponse(200, $response);
});

/**
 * Load categories
 * method POST
 * url /allCategories
 */
$app->post('/allCategories', 'authenticate', function() use ($app) {

    global $user_id;
    $response = array();
    $db = new DbHandler();

    $response["categories"] = $db->getAllCategories();

    $response["error"] = false;

    echoResponse(200, $response);
});

/**
 * Add category
 * method POST
 * url /addCategory
 */
$app->post('/addCategory', 'authenticate', function() use ($app) {

    verifyRequiredParams(array('Title'));
    global $user_id;
    $response = array();
    $db = new DbHandler();

    $Title = $app->request->post('Title');

    $db->addCategory($Title);

    $response["error"] = false;

    echoResponse(200, $response);
});

/**
 * Rename category
 * method POST
 * url /renameCategory
 */
$app->post('/renameCategory', 'authenticate', function() use ($app) {

    verifyRequiredParams(array('Id', 'NewTitle'));

    global $user_id;
    $response = array();
    $db = new DbHandler();

    $Id = $app->request->post('Id');
    $NewTitle = $app->request->post('NewTitle');

    $response = $db->renameCategory($Id, $NewTitle);

    echoResponse(200, $response);
});

/**
 * Enables or disables a category
 * method POST
 * url /enableCategory
 */
$app->post('/enableCategory', 'authenticate', function() use ($app) {

    verifyRequiredParams(array('Id', 'Enabled'));

    global $user_id;
    $response = array();
    $db = new DbHandler();

    $Id = $app->request->post('Id');
    $Enabled = $app->request->post('Enabled');

    $db->enableCategory($Id, $Enabled);

    $response["error"] = false;

    echoResponse(200, $response);
});

/**
 * Remove category and all questions under it
 * method POST
 * url /removeCategory
 */
$app->post('/removeCategory', 'authenticate', function() use ($app) {

    verifyRequiredParams(array('Id'));

    global $user_id;
    $response = array();
    $db = new DbHandler();

    $Id = $app->request->post('Id');

    $db->removeCategory($Id);

    $response["error"] = false;

    echoResponse(200, $response);
});

/**
 * Load models
 * method POST
 * url /allModels
 */
$app->post('/allModels', 'authenticate', function() use ($app) {

    global $user_id;
    $response = array();
    $db = new DbHandler();

    $response["models"] = $db->getAllModels();

    $response["error"] = false;

    echoResponse(200, $response);
});

/**
 * Add model
 * method POST
 * url /addCategory
 */
$app->post('/addModel', 'authenticate', function() use ($app) {

    verifyRequiredParams(array('Title'));
    global $user_id;
    $response = array();
    $db = new DbHandler();

    $Title = $app->request->post('Title');

    $db->addModel($Title);

    $response["error"] = false;

    echoResponse(200, $response);
});

/**
 * Rename model
 * method POST
 * url /renameModel
 */
$app->post('/renameModel', 'authenticate', function() use ($app) {

    verifyRequiredParams(array('Id', 'NewTitle'));

    global $user_id;
    $response = array();
    $db = new DbHandler();

    $Id = $app->request->post('Id');
    $NewTitle = $app->request->post('NewTitle');

    $response = $db->renameModel($Id, $NewTitle);

    echoResponse(200, $response);
});

/**
 * Enables or disables a model
 * method POST
 * url /enableCategory
 */
$app->post('/enableModel', 'authenticate', function() use ($app) {

    verifyRequiredParams(array('Id', 'Enabled'));

    global $user_id;
    $response = array();
    $db = new DbHandler();

    $Id = $app->request->post('Id');
    $Enabled = $app->request->post('Enabled');

    $db->enableModel($Id, $Enabled);

    $response["error"] = false;

    echoResponse(200, $response);
});

/**
 * Remove model and all questions under it
 * method POST
 * url /removeModel
 */
$app->post('/removeModel', 'authenticate', function() use ($app) {

    verifyRequiredParams(array('Id'));

    global $user_id;
    $response = array();
    $db = new DbHandler();

    $Id = $app->request->post('Id');

    $db->removeModel($Id);

    $response["error"] = false;

    echoResponse(200, $response);
});

/**
 * Load technologies
 * method POST
 * url /allTechnologies
 */
$app->post('/allTechnologies', 'authenticate', function() use ($app) {

    global $user_id;
    $response = array();
    $db = new DbHandler();

    $response["technologies"] = $db->getAllTechnologies();

    $response["error"] = false;

    echoResponse(200, $response);
});

/**
 * Add technology
 * method POST
 * url /addCategory
 */
$app->post('/addTechnology', 'authenticate', function() use ($app) {

    verifyRequiredParams(array('Title'));
    global $user_id;
    $response = array();
    $db = new DbHandler();

    $Title = $app->request->post('Title');

    $db->addTechnology($Title);

    $response["error"] = false;

    echoResponse(200, $response);
});

/**
 * Rename technology
 * method POST
 * url /renameTechnology
 */
$app->post('/renameTechnology', 'authenticate', function() use ($app) {

    verifyRequiredParams(array('Id', 'NewTitle'));

    global $user_id;
    $response = array();
    $db = new DbHandler();

    $Id = $app->request->post('Id');
    $NewTitle = $app->request->post('NewTitle');

    $response = $db->renameTechnology($Id, $NewTitle);

    echoResponse(200, $response);
});

/**
 * Enables or disables a technology
 * method POST
 * url /enableCategory
 */
$app->post('/enableTechnology', 'authenticate', function() use ($app) {

    verifyRequiredParams(array('Id', 'Enabled'));

    global $user_id;
    $response = array();
    $db = new DbHandler();

    $Id = $app->request->post('Id');
    $Enabled = $app->request->post('Enabled');

    $db->enableTechnology($Id, $Enabled);

    $response["error"] = false;

    echoResponse(200, $response);
});

/**
 * Remove technology and all questions under it
 * method POST
 * url /removeModel
 */
$app->post('/removeTechnology', 'authenticate', function() use ($app) {

    verifyRequiredParams(array('Id'));

    global $user_id;
    $response = array();
    $db = new DbHandler();

    $Id = $app->request->post('Id');

    $db->removeTechnology($Id);

    $response["error"] = false;

    echoResponse(200, $response);
});

/**
 * Get random question
 * method POST
 * url /getQuestion
 */
$app->post('/getQuestion', 'authenticate', function() use ($app) {

    global $user_id;
    $response = array();
    $db = new DbHandler();

    $response = $db->getQuestion($user_id);

    echoResponse(200, $response);
});

/**
 * Report question
 * method POST
 * url /report
 */
$app->post('/report', 'authenticate', function() use ($app) {

    verifyRequiredParams(array('QuestionId', 'Attempts', 'Time'));
    global $user_id;
    $db = new DbHandler();

    $QuestionId = $app->request->post('QuestionId');
    $Attempts = $app->request->post('Attempts');
    $Time = $app->request->post('Time');

    $response = $db->report($user_id, $QuestionId, $Attempts, $Time);

    echoResponse(200, $response);
});

/**
 * Get last question timestamp
 * method POST
 * url /getLastTimestamp
 */
$app->post('/getLastTimestamp', 'authenticate', function() use ($app) {

    global $user_id;
    $response = array();
    $db = new DbHandler();

    $response = $db->getLastTimestamp($user_id);

    echoResponse(200, $response);
});

/**
 * Sends push notifications from admin
 * method POST
 * url /sendPush
 */
$app->post('/sendPush', 'authenticate', function() use ($app) {

    verifyRequiredParams(array('Title', 'Message'));

    global $user_id;
    $response = array();
    $db = new DbHandler();

    $Title = $app->request->post('Title');
    $Message = $app->request->post('Message');

    $db->sendPush($Title, $Message);

    $response["error"] = false;

    echoResponse(200, $response);
});

/**
 * Used to update lastTimestamp, and say that user is online
 * method POST
 * url /sendPush
 */
$app->post('/imHere', 'authenticate', function() use ($app) {

    global $user_id;
    $response = array();
    $db = new DbHandler();

    $db->imHere($user_id);

    $response["error"] = false;

    echoResponse(200, $response);
});

/**
 * Used to end current session
 * method POST
 * url /endSession
 */
$app->post('/endSession', 'authenticate', function() use ($app) {

    verifyRequiredParams(array('sessionId'));

    global $user_id;
    $response = array();
    $db = new DbHandler();

    $sessionId = $app->request->post('sessionId');

    $db->endSession($sessionId, $user_id);

    $response["error"] = false;

    echoResponse(200, $response);
});

/**
 * Used to end current session
 * method POST
 * url /endSession
 */
$app->post('/logMessage', 'authenticate', function() use ($app) {

    verifyRequiredParams(array('FromWho', 'Message'));

    global $user_id;
    $response = array();
    $db = new DbHandler();

    $FromWho = $app->request->post('FromWho');
    $Message = $app->request->post('Message');

    $db->logMessage($user_id, $FromWho, $Message);

    $response["error"] = false;

    echoResponse(200, $response);
});

/**
 * Used to see reports for an user
 * method POST
 * url /reports
 */
$app->post('/reports', 'authenticate', function() use ($app) {

    verifyRequiredParams(array('Id'));

    global $user_id;
    $response = array();
    $db = new DbHandler();

    $UserId = $app->request->post('Id');

    $response = $db->getReports($UserId);

    echoResponse(200, $response);

    $parsedBody = $app->request->getBody();

    var_dump($parsedBody);
});

/**
 * Used to log locations
 * method POST
 * url /logLocation
 */
$app->post('/logLocation', 'authenticate', function() use ($app) {

    verifyRequiredParams(array('location'));

    global $user_id;
    $response = array();
    $db = new DbHandler();

    $location = $app->request->post('location');

    $db->logLocation($user_id, $location);

    $response["error"] = false;

    echoResponse(200, $response);
});

$app->run();
?>