<?php

	define('APS_DEVELOPMENT_MODE', true);
	require "aps/2/runtime.php";
	require "rest-utils.php";

	class LicCounter {
		/**
		 * @type("integer")
		 * @title("License Limit")
		 * @description("The total number of repositories allowed by the license")
		 */
		public $licLimit;

		/**
		 * @type("integer")
		 * @title("License Usage")
		 * @description("The total number of created repositories")
		 */
		public $licUsage;
	}

	/**
	* @type("http://aps-standard.org/samples/github/tenant/1.0")
	* @implements("http://aps-standard.org/types/core/subscription/service/1.0")
	*/

	class tenant extends \APS\ResourceBase
	{
		## Strong link to the application instance
		/**
		 * @link("http://aps-standard.org/samples/github/app/1.0")
		 * @required
		 */
		public $app;

        ## Strong link to the reseller
        /**
         * @link("http://aps-standard.org/samples/github/reseller/1.0")
         * @required
         */
        public $reseller;

        ## Weak link to a license; the provisioning logic must set the proper link
		/**
		 * @link("http://aps-standard.org/samples/github/license/1.0")
		 */
		public $license;

        /**
         * @type(string)
         * @title("BaseURL")
         * @description("Base URL of the cloud application endpoint")
         */
        public $baseURL;

		/**
		 * @type(string)
		 * @title("Token")
		 * @description("User token for the tenant generated by the cloud application")
		 */
		public $token;

		/**
		 * @type(integer)
		 * @title("TokenID")
		 * @description("User token ID for the tenant generated by the cloud application")
		 */
		public $tokenId;

		/**
		 * @type(string[])
		 * @title("SecurityScopes")
		 * @description("Access to the application objects. Depends on the acquired license.")
		 */
		public $scopes;

		/**
		 * @type(string)
		 * @title("RepoNamePrefix")
		 * @description("The prefix to be added to every repository created by the tenant")
		 */
		public $repoNamePrefix;

		/**
		 * @type(string)
		 * @title("UserAgent")
		 * @description("Sent in the User-Agent HTTP header as required by some operations of the application API")
		 */
		public $userAgent;

		## This is a custom counter created for demo purposes only - to show the number of created repos in UI
		/**
		 * @type(LicCounter)
		 * @title("License Limit and Usage")
		 * @description("The total number of repositories used by the tenant and allowed by the license")
		 */
		public $licenseCounter;


		public function provision() {
            $logger = \APS\LoggerRegistry::get();
            $companyName = $this->account->companyName;
            ## Interact with the APS controller for getting additional data
            $apsc = \APS\Request::getController();

            ## Get data from the subscription:
            $subscriptionId = $this->subscription->aps->id;
            $resources = json_decode($apsc->getIo()->sendRequest(\APS\Proto::GET,
                "/aps/2/resources/".$subscriptionId."/resources"));

            ## Find the license with the non-zero limit and set the license counter:
            foreach($resources as $resource) {
                if($resource->apsType == "http://aps-standard.org/samples/github/license/1.0" &&
                      $resource->limit > 0) {
                    # Link the tenant with the license:
                    $logger->info("Request for link: ".$this."/license with ".$resource->apsId);
                    $apsc->linkResource($this, "license", $resource->apsId);

                    # Initialize the license counter:
                    $this->licenseCounter = new stdClass();
                    $this->licenseCounter->licLimit = $resource->limit;
                    $this->licenseCounter->licUsage = 0;
                    $logger->info("License Counter: ".print_r($this->licenseCounter, true));
                    break;
                }
            }

            $this->scopes = $this->license->scopes;

            ## Get the API URL from the App instance
            # Ensure the slash at the end of the URL
            $this->baseURL = rtrim($this->app->baseURL, '/') . '/';

            ## Get login name and password from the reseller
            $login = $this->reseller->login;
            $passwd = $this->reseller->passwd;

            ## Use the customer's admin email as the User Agent for the application API
            $this->userAgent = $this->account->adminContact->email;

            ## HTTP method and URL:
            $verb = 'POST';
            $url = $this->baseURL . 'authorizations';

            ## Payload for the request
            $payload = array(
               'scopes' => $this->scopes,
               'note' => $companyName
            );

            ## Send REST request to generate a user token for the tenant
            $response = rest_request_basic($url, $verb, $login, $passwd, $this->userAgent, $payload);
            if($response) {
               $this->token = $response->token;
               $this->tokenId = $response->id;
            }

            ## Repo names to be created later must begin with the following prefix
            $this->repoNamePrefix = makeRepoName($companyName);
		}

      ## Custom method to retrieve repositories from the App side
		/**
         * @verb(GET)
         * @path("/repos")
         * @return(object)
         */
         public function getRepos() {

            $verb = 'GET';
            $url = $this->baseURL.'user/repos';
            $token = $this->token;

            $response = rest_request($url, $verb, $token, $this->userAgent);

            $returnData = [];

            if($response) {
                foreach ($response as $repo) {
                    if($repo->name )
                        $name = $repo->name;
                    if(strpos($name, $this->repoNamePrefix) === 0) {
                        array_push($returnData,
                            array(
                                "id" => $repo->id,
                                "name" => $repo->name,
                                "url" => $repo->html_url
                            ));
                    }
                }
            }

            return $returnData;
         }

        ## Custom method to refresh the repo usage in the license counter
        /**
         * @verb(GET)
         * @path("/refreshdata")
         * @return(object)
         */
        public function refreshData() {
            $this->licenseCounter->licUsage = count($this->getRepos());
            $apsc = \APS\Request::getController();
            $apsc->updateResource($this);
        }

        ## Custom method to create a Repository on the App side
        /**
         * @verb(POST)
         * @path("/repos")
         * @param(string,body)
         * @return(object)
         */
        public function createRepo($name) {
            $this->licenseCounter->licUsage = count($this->getRepos());
            if($this->licenseCounter->licUsage >= $this->licenseCounter->licLimit) return;

            $repoName = $this->repoNamePrefix.'_'.makeRepoName($name->name_suffix);

            $verb = 'POST';
            $url = $this->baseURL.'user/repos';
            $token = $this->token;
            $payload = array('name' => $repoName);
            $response = rest_request($url, $verb, $token, $this->userAgent, $payload);

            $this->licenseCounter->licUsage = count($this->getRepos());
            $apsc = \APS\Request::getController();
            $apsc->updateResource($this);

            return $response;
        }

        ## Custom method to remove a Repository on the App side
        /**
         * @verb(DELETE)
         * @path("/repos/{name}")
         * @param(string,path)
         */
        public function removeRepo($name) {
            $logger = \APS\LoggerRegistry::get();

            $verb = 'DELETE';
            $url = $this->baseURL.'repos/'.$this->reseller->login.'/'.$name;
            $token = $this->token;
            $agent = $this->userAgent;

            $response = rest_request($url, $verb, $token, $agent);
            if($response) {
                $logger->info("\nRESPONSE received by the requester: ".$response."\n");
            }
            else $logger->info("No response - see details in /var/log/httpd/error.log \n");

            ## Update the counter in the APS DB
            $this->licenseCounter->licUsage = count($this->getRepos());
            $apsc = \APS\Request::getController();
            $apsc->updateResource($this);

        }

        # Event handler - used to update the license counter when the subscription is updated
        /**
         * @verb(POST)
         * @path("/onLimitChange")
         * @param("http://aps-standard.org/types/core/resource/1.0#Notification",body)
         */
        public function onLimitChange($notification) {
            $apsc = \APS\Request::getController();

            ## Get data from the subscription:
            $subscriptionId = $this->subscription->aps->id;
            $resources = json_decode($apsc->getIo()->sendRequest(\APS\Proto::GET,
                "/aps/2/resources/".$subscriptionId."/resources"));

            foreach($resources as $resource) {
                if($this->license->aps->type == $resource->apsType) {
                    $this->licenseCounter->licLimit = $resource->limit;
                    break;
                }
            }
            $logger->info("License Counter: ".$this->licenseCounter);
            $apsc->updateResource($this);
        }

        public function unprovision() {
            ## Get login name and password from the reseller for DELETE repos
            $login = $this->reseller->login;
            $passwd = $this->reseller->passwd;
            ## HTTP method and URL:
            $verb = 'DELETE';

            ## Parameters for GET repos
            $url = $this->baseURL.'user/repos';
            $token = $this->token;

            $repos = rest_request($url, 'GET', $token, $this->userAgent);
            foreach ($repos as $repo) {
                $name = $repo->name;
                if(strpos($name, $this->repoNamePrefix) === 0) {
                    $url = $this->baseURL.'repos/'.$this->reseller->login.'/'.$name;
                    rest_request_basic($url, $verb, $login, $passwd);
                }
            }

            $url = $this->baseURL.'authorizations/'.$this->tokenId;
            rest_request_basic($url, 'DELETE', $login, $passwd);
        }
    }
?>
