<?php

/*
 * TODO
 *  Better logging instantiation/customization
 *  Config handling class
 *  Make it easier to set response code and output error
 *  Check user<->game permissions
 */

require 'Outspark/3rdparty/Restafarian/restafarian_common.php';
require_once 'Outspark/Common/KeyMaster/KeyMaster.php';
require_once 'Outspark/Store/Store.php';
require_once 'Outspark/Platform/Store/UserInventory.php';

require '../OSKSignedRestResource.inc';

// Set up logging
include_once 'Log.php';
$GLOBALS['logger'] = Log::factory('file', '/tmp/osk_error.log', 'StoreResource');
if (is_null($GLOBALS['logger'])) {
	exit("Unable to initiate Logging");
}

class StoreResource extends OSKRestResource
{
	public function dispatch ($req)
	{
		$next = $this;
		$version = $this->getNextRawSegment();

		/*
		 * If version doesn't match, return /user resource
		 */
		if ($version != 'v1') {
			return $this;
		}

		/*
		 * Get the portion after version
		 */
		$this->incrementNextIndex();
		$segment = $this->getNextRawSegment();

		switch ($segment) {
			case 'getPurchasedItems':
				$next = new GetPurchasedItemsResource();
				break;

			case 'setItemUsed':
				$next = new SetItemUsedResource();
				break;

			case 'setItemActivated':
				$next = new SetItemActivatedResource();
				break;

			case 'manageOutsparkItem':
				$next = new ManageOutsparkItemResource();
				break;
			case 'listItems':
                $next = new ListItemsResource();
                break;
			case 'purchaseItem':
				$next = new DoItemTransactionResource();
				break;
			case 'buyItems':
				$next = new BuyItemsResource();
				break;
			default:
				// no default action
				break;
		}

		return $next;
	}

	public function GET ($req, $resp)
	{
		/*
		 * Anything not handled under /store is an error.
		 */
		$resp->setStatusCode(REST_STATUS_BAD_REQUEST);
		$resp->makeError($this, $resp->getStatusCode(), "Bad Request");
	}
}
class ListItemsResource extends OSKRestResource{
    public function GET($req, $resp){
        $params = $req->getUri()->getQueryParams();
        $realm = $params->getFirst('realm');
		if (empty($realm)) {
			$resp->setStatusCode(REST_STATUS_BAD_REQUEST);
			$resp->makeError($this, $resp->getStatusCode(), 'Bad request');
			return;
		}
        $modified = $params->getFirst('modified');
        if(empty($modified)){
            $modified = 0;
        }
        $modified = date("Y-m-d H:i:s", $modified);
        
        $storedbc = StoreDB::getDB(); // for now
        $query = "SELECT * FROM realmitem WHERE realm=:realm and modified >=:modified";
        $stmt = $storedbc->prepare($query);
        try{
            $stmt->execute(array(":realm" => $realm, ":modified" => $modified));
            $result = array();
			$result["timestamp"] = (int)time();
            $result["count"] = (int)$stmt->rowCount();
            $result["items"] = array();
            foreach($stmt->fetchAll(PDO::FETCH_ASSOC) as $row){
                if(empty($row["pacakge"])){// ignore packages
                    $item = array();
	                    $item["itemid"] = (int)$row["itemid"];
	                    $item["price"] = (int)$row["price"];
	                    $item["discount"] = (int)$row["discount"];
	                    $item["purchasestart"] = $row["purchasestart"];
	                    $item["purchaseend"] = $row["purchaseend"];
	                    $item["discountstart"] = $row["discountstart"];
	                    $item["discountend"] = $row["discountend"];
                    $result["items"][] = $item;
                }
            }
            }catch(Exception $e){
                $jnk = $e->getMessage();
            }
		$output = $params->getFirst('output');
		if (empty($output)) {
			$output = 'json';
		}
        
		$json = json_encode($result);

		if ($output == 'text') {
			$resp->setContent(CTYPE_TEXT, $json);
		} else {
			$resp->setContent(CTYPE_JSON, $json);
		}
		$resp->setStatusCode(REST_STATUS_OK);
    }
}
class GetPurchasedItemsResource extends OSKSignedRestResource {

	public function signedGET ($req, $resp)
	{
		
		$params = $req->getUri()->getQueryParams();

		$realm = $params->getFirst('realm');
		$outsparkID = $params->getFirst('outsparkID');
        $userid = $params->getFirst('userID');
        if(!empty($userid)){
            $outsparkID = $userid;
        }

		$output = $params->getFirst('output');
		if (empty($output)) {
			$output = 'json';
		}

		if (empty($outsparkID) || empty($realm)) {
			$resp->setStatusCode(REST_STATUS_BAD_REQUEST);
			$resp->makeError($this, $resp->getStatusCode(), 'Bad request');
			return;
		}

		$store = new OSKStore($realm);
		$orderItems = $store->getUnusedOSKItemsByUserID($outsparkID);
		$userinventory = new UserInventory($outsparkID, $realm);
		$orderItems = array_merge($orderItems, $userinventory->getUnusedItems());
		$orderItems = array_slice($orderItems, 0, 100); // only return 100 for now
		$resultItems = array();
		foreach ($orderItems as $item) {
			if("OSKOrderItem" == get_class($item)){
				$resultItems[] = array('orderItemID' => (int)$item->getOrderItemID(),
									   'gameItemID'  => (int)$item->getInGameItemID(),
									   'orderTime'   => (int)$item->getOrderTime(),
									   'quantity'    => 1,
									   'isUsed'      => (bool)$item->getIsDraw());
			}else{
				$resultItems[] = array('orderItemID' => (int)$item['useritemid'],
							'gameItemID' => (int)$item['itemid'],
							'orderTime' => strtotime($item['purchased']),
							'quantity' => 1,
							'isUsed' => false
							);
			}
		}
		$GLOBALS['logger']->debug("{$outsparkID}: getPurchasedItems : returning ".count($resultItems)." items");

		$json = json_encode(array('items' => $resultItems));

		if ($output == 'text') {
			$resp->setContent(CTYPE_TEXT, $json);
		} else {
			$resp->setContent(CTYPE_JSON, $json);
		}
		$resp->setStatusCode(REST_STATUS_OK);
	}

}

class SetItemUsedResource extends OSKSignedRestResource {

	public function signedGET ($req, $resp)
	{
		$params = $req->getUri()->getQueryParams();

		$realm = $params->getFirst('realm');
		$outsparkID = $params->getFirst('outsparkID');
        $userid = $params->getFirst('userID');
        if(!empty($userid)){
            $outsparkID = $userid;
        }
		$worldID = $params->getFirst('worldID');
		$characterID = $params->getFirst('characterID');
		$orderItemID = $params->getFirst('orderItemID');

		$output = $params->getFirst('output');

		if (empty($realm) || empty($outsparkID) || empty($orderItemID) || !isset($worldID) || !isset($characterID)) {
			$resp->setStatusCode(REST_STATUS_BAD_REQUEST);
			$resp->makeError($this, $resp->getStatusCode(), 'Bad request');
			return;
		}

		if (empty($output)) {
			$output = 'json';
		}
		// try the new store library first, since we know it's more strict in the flagging
		try{
			$userinventory = new UserInventory($outsparkID, $realm);
			$result = $userinventory->setUsed($orderItemID);
		}catch(Exception $e){
			$result = false; // looks like i wasn't able to flag using new library
		}
		if(!$result){
			// wasn't successfull for some reason, it's probably
			// an item from the old library
			$store = OSKStore::getInstance($realm);
			$result = $store->setIsDraw($orderItemID);
		}
		if(!$result){
			// old store lib wasn't able to activate, try new store lib.
		}
		$json = json_encode(array('result' => $result));

		if ($output == 'text') {
			$resp->setContent(CTYPE_TEXT, $json);
		} else {
			$resp->setContent(CTYPE_JSON, $json);
		}
		$resp->setStatusCode(REST_STATUS_OK);
	}

}

class SetItemActivatedResource extends OSKSignedRestResource {

	public function signedGET ($req, $resp)
	{
		$params = $req->getUri()->getQueryParams();

		$realm = $params->getFirst('realm');
		$outsparkID = $params->getFirst('outsparkID');
        $userid = $params->getFirst('userID');
        if(!empty($userid)){
            $outsparkID = $userid;
        }
		$worldID = $params->getFirst('worldID');
		$characterID = $params->getFirst('characterID');
		$orderItemID = $params->getFirst('orderItemID');

		$output = $params->getFirst('output');

		if (empty($realm) || empty($outsparkID) || empty($orderItemID) || !isset($worldID) || !isset($characterID)) {
			$resp->setStatusCode(REST_STATUS_BAD_REQUEST);
			$resp->makeError($this, $resp->getStatusCode(), 'Bad request');
			return;
		}

		if (empty($output)) {
			$output = 'json';
		}

		$store = OSKStore::getInstance($realm);
		$result = $store->setItemActivated($orderItemID);
		$json = json_encode(array('result' => $result));

		if ($output == 'text') {
			$resp->setContent(CTYPE_TEXT, $json);
		} else {
			$resp->setContent(CTYPE_JSON, $json);
		}
		$resp->setStatusCode(REST_STATUS_OK);
	}

}

/**
 * ManageOutsparkItemResource primes request arguments and acts as a handler for the request,
 * dependant on the specified action parameter (action=create|read|update|delete)
 *
 */
class ManageOutsparkItemResource extends OSKSignedRestResource {
	
	public function signedGET ($req, $resp) {
		global $logger;
		require("Outspark/Store/Types/OSKItemDAL.php");
		
		$params = $req->getUri()->getQueryParams();
		$names = $params->getNames();	// fetch all parameters from request
		$args = $params->asArray();
		if ($args['action']) {
			$action = $args['action'];
		}
		$output = (empty($args['output'])) ? "json" : $args['output'];
		
		if (isset($args["realm"])) {	// quick fix for game<->discrepancy
			$args["game"] = $args["realm"];
			unset($args["realm"]);
		}
		
		$field =	(isset($args['field']) && !empty($args['field'])) ? $args['field'] : false;
		
		$Item = new OSKItemDAL();
		$cols = $Item->fetchDatabaseFields(true);	// fetch all fields from database table, TRUE = to use values as array keys
		$args = array_intersect_key($args, $cols);
		
		//$logger->debug(print_r($args,1));
		
		switch (strtolower($action)) {	// handle request
			case "create":
			case "add":
				if (!$args['inGameItemID'] || empty($args['game'])) {
					$resp->setStatusCode(REST_STATUS_BAD_REQUEST);
					$resp->makeError($this, $resp->getStatusCode(), 'Bad request');
					return;
				}
				$return_val = $Item->create($args);
				break;
			case "fetch":
			case "read":
				if (!$args['inGameItemID'] || empty($args['game'])) {
					$resp->setStatusCode(REST_STATUS_BAD_REQUEST);
					$resp->makeError($this, $resp->getStatusCode(), 'Bad request');
					return;
				}
				$return_val = $Item->fetch($args, $field);
				break;
			case "update":
				if (!$args['inGameItemID'] || empty($args['game'])) {
					$resp->setStatusCode(REST_STATUS_BAD_REQUEST);
					$resp->makeError($this, $resp->getStatusCode(), 'Bad request');
					return;
				}
				$return_val = $Item->update($args);
				break;
			case "delete":
				if (!$args['oskItemID']) {
					$resp->setStatusCode(REST_STATUS_BAD_REQUEST);
					$resp->makeError($this, $resp->getStatusCode(), 'Bad request');
					return;
				}
				$return_val = $Item->delete($args['game'], $args['oskItemID']);
				break;
			default:
				$resp->setStatusCode(REST_STATUS_BAD_REQUEST);
				$resp->makeError($this, $resp->getStatusCode(), 'Bad request');
				return;
				break;
		}
		
		$result = ($return_val != true) ? "failed" : "success";
		$resp_array = array("result" => $result, "values" => $return_val);
		
		//$logger->debug(print_r($resp_array, 1));
		$logger->debug(__METHOD__."; action = $action; result = $result; value = $return_val");
		
		$json = json_encode($resp_array);
		if ($output == "text") {
			$resp->setContent(CTYPE_TEXT, $json);
		} else {
			$resp->setContent(CTYPE_JSON, $json);
		}
		$resp->setStatusCode(REST_STATUS_OK);
	}
}

class DoItemTransactionResource extends OSKSignedRestResource {
	
	public function signedGET ($req, $resp) {
		global $logger;
		require("Outspark/Store/Types/OSKItemTransaction.php");
		
		$params = $req->getUri()->getQueryParams();
		
		/* To Do: change vars to reflect change from game to realm */
		$return_val = false;	
		$game = $params->getFirst("realm");
		$output = $params->getFirst("output");
		$output = (empty($output)) ? "json" : "text";	
		if (!$game) {
			$resp->setStatusCode(REST_STATUS_BAD_REQUEST);
			$resp->makeError($this, $resp->getStatusCode(), "Bad request");
			exit;
		}
		$Transaction = new OSKItemTransaction($game);
		try {
			// $return_val = transaction ID on success; on failure, "bad request" page triggered, showing the cause of failure
			$return_val = $Transaction->purchase($params->getFirst("userID"), $params->getFirst("oskItemID"));
		} catch (Exception $e) {
			$err = $e->getMessage();
		} catch (OSKInsufficientFundsException $e) {
			$err = $e->getMessage();
		}
		$result = ($return_val != true) ? "failed" : "success";
		if (!empty($err)) {
			$return_val = false;
		}
		$resp_array = array("result" => $result, "values" => $return_val);
		
		$logger->debug("purchaseItem: result = $result, value= $return_val");

		$json = json_encode($resp_array);
		if ($output == "text") {
			$resp->setContent(CTYPE_TEXT, $json);
		} else {
			$resp->setContent(CTYPE_JSON, $json);
		}
		$resp->setStatusCode(REST_STATUS_OK);
	}
	
}

class BuyItemsResource extends OSKSignedRestResource {
	
	const ERROR_ITEM_NOT_FOUND = 1;
	const ERROR_INSUFFICIENT_FUNDS = 2;
	const ERROR_NO_ITEMS_LISTED = 3;
	const ERROR_UNKNOWN = 4;
	
	public function signedGET ($req, $resp) {
		global $logger;
		require_once("Outspark/Platform/Store/RealmStore.php");
		$params = $req->getUri()->getQueryParams();
		$output = $params->getFirst("output");
		$output = (empty($output)) ? "json" : "text";	
		$realm = $params->getFirst("realm");

		if (!$realm) {
			$resp->setStatusCode(REST_STATUS_BAD_REQUEST);
			$resp->makeError($this, $resp->getStatusCode(), "Bad request");
			exit;
		}
		
		
		$store = new RealmStore($realm);
		$inventory = $store->getRealmInventory();
		$item_list = array();

		$result = 0;
		$error = null;
		$error_text = null;
		$transaction_id = '';
		$total = 0;
		
		$inGameItemIDs = explode(",", $params->getFirst("inGameItemIDs"));
		
		$error = count($inGameItemIDs) > 0? null: self::ERROR_NO_ITEMS_LISTED;
		if($error == null){
			foreach($inGameItemIDs as $inGameItemID){
				if(!empty($inGameItemID)){
					$item = $inventory->getRealmItem($inGameItemID);
					if($item != null){
						$item_list[] = $item;
					}else{
						$error = self::ERROR_ITEM_NOT_FOUND;
					}
				}
			}
		
			if($error == null){
				
				$userID = $params->getFirst("userID");
				
				try {
					foreach($item_list as $item){
						$transaction_id = $store->buy($item, $userID);
						$total += $item->getPrice() - $item->getDiscount();
						$result = 1;
					}
				} catch (OSKInsufficientFundsException $e) {
					$error = self::ERROR_INSUFFICIENT_FUNDS;
					$error_text = get_class($e);
				} catch (Exception $e) {
					$error = self::ERROR_UNKNOWN;
					$error_text = get_class($e);
				}
			}
		}

		$response = array("result" => $result,
			  "total" => $total,
			  "transaction" => $transaction_id,
			  "error" => $error,
			  "error_text" => $error_text
			  );
		

		$json = json_encode($response);
		if ($output == "text") {
			$resp->setContent(CTYPE_TEXT, $json);
		} else {
			$resp->setContent(CTYPE_JSON, $json);
		}
		$resp->setStatusCode(REST_STATUS_OK);
	}
	
}

?>
