<?php
/**
 * 2007-2014 [PagSeguro Internet Ltda.]
 *
 * NOTICE OF LICENSE
 *
 *Licensed under the Apache License, Version 2.0 (the "License");
 *you may not use this file except in compliance with the License.
 *You may obtain a copy of the License at
 *
 *http://www.apache.org/licenses/LICENSE-2.0
 *
 *Unless required by applicable law or agreed to in writing, software
 *distributed under the License is distributed on an "AS IS" BASIS,
 *WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *See the License for the specific language governing permissions and
 *limitations under the License.
 *
 *  @author    PagSeguro Internet Ltda.
 *  @copyright 2007-2014 PagSeguro Internet Ltda.
 *  @license   http://www.apache.org/licenses/LICENSE-2.0
 */

/***
 * Encapsulates web service calls regarding PagSeguro notifications
 */
class PagSeguroNotificationService
{

    /***
     *
     */
    const SERVICE_NAME = 'notificationService';

    /**
     * @var
     */
    private static $service;


    /**
     * @param PagSeguroConnectionData $connectionData
     * @param $notificationCode
     * @return string
     */
    private static function buildTransactionNotificationUrl(
        PagSeguroConnectionData $connectionData,
        $notificationCode
    ) {
        $url = $connectionData->getServiceUrl();
        return "{$url}/{$notificationCode}/?" . $connectionData->getCredentialsUrlQuery();
    }


    /**
     * @param PagSeguroConnectionData $connectionData
     * @param $notificationCode
     * @return string
     */
    private static function buildAuthorizationNotificationUrl(
        PagSeguroConnectionData $connectionData,
        $notificationCode
    ) {
        $url = $connectionData->getWebserviceUrl() . '/' . $connectionData->getResource('applicationPath');
        return "{$url}/{$notificationCode}/?" . $connectionData->getCredentialsUrlQuery();
    }


    /**
     * @param PagSeguroConnectionData $connectionData
     * @param $preApprovalCode
     * @return string
     */
    private static function buildPreApprovalNotificationUrl(
        PagSeguroConnectionData $connectionData,
        $preApprovalCode
    ) {
        $url = $connectionData->getWebserviceUrl() . '/' . $connectionData->getResource('preApprovalPath');
        return "{$url}/{$preApprovalCode}/?" . $connectionData->getCredentialsUrlQuery();
    }

    /***
     * Returns a transaction from a notification code
     *
     * @param PagSeguroCredentials $credentials
     * @param String $notificationCode
     * @throws PagSeguroServiceException
     * @throws Exception
     * @return PagSeguroTransaction
     * @see PagSeguroTransaction
     */
    public static function checkTransaction(PagSeguroCredentials $credentials, $notificationCode)
    {

        LogPagSeguro::info(
            "PagSeguroNotificationService.CheckTransaction(notificationCode=$notificationCode) - begin"
        );
        $connectionData = new PagSeguroConnectionData($credentials, self::SERVICE_NAME);

        try {
            $connection = new PagSeguroHttpConnection();
            $connection->get(
                self::buildTransactionNotificationUrl($connectionData, $notificationCode),
                $connectionData->getServiceTimeout(),
                $connectionData->getCharset()
            );

            self::$service = "CheckTransaction";
            return self::getResult($connection, $notificationCode);

        } catch (PagSeguroServiceException $err) {
            throw $err;
        } catch (Exception $err) {
            LogPagSeguro::error("Exception: " . $err->getMessage());
            throw $err;
        }
    }

    /**
     * Returns a authorization from a notification code
     * @param PagSeguroCredentials $credentials
     * @param $notificationCode
     * @return bool|mixed|string
     * @throws Exception
     * @throws PagSeguroServiceException
     */
    public static function checkAuthorization(PagSeguroCredentials $credentials, $notificationCode)
    {

        LogPagSeguro::info(
            "PagSeguroNotificationService.CheckAuthorization(notificationCode=$notificationCode) - begin"
        );

        $connectionData = new PagSeguroConnectionData($credentials, self::SERVICE_NAME);

        try {
            $connection = new PagSeguroHttpConnection();
            $connection->get(
                self::buildAuthorizationNotificationUrl($connectionData, $notificationCode),
                $connectionData->getServiceTimeout(),
                $connectionData->getCharset()
            );

            self::$service = "CheckAuthorization";
            return self::getResult($connection, $notificationCode);

        } catch (PagSeguroServiceException $err) {
            throw $err;
        } catch (Exception $err) {
            LogPagSeguro::error("Exception: " . $err->getMessage());
            throw $err;
        }
    }

    /**
     * Returns a pre approval from a notification code
     * @param PagSeguroCredentials $credentials
     * @param $notificationCode
     * @return bool|mixed|string
     * @throws Exception
     * @throws PagSeguroServiceException
     */
    public static function checkPreApproval(PagSeguroCredentials $credentials, $notificationCode)
    {

        LogPagSeguro::info(
            "PagSeguroNotificationService.CheckPreApproval(notificationCode=$notificationCode) - begin"
        );

        $connectionData = new PagSeguroConnectionData($credentials, self::SERVICE_NAME);

        try {
            $connection = new PagSeguroHttpConnection();
            $connection->get(
                self::buildPreApprovalNotificationUrl($connectionData, $notificationCode),
                $connectionData->getServiceTimeout(),
                $connectionData->getCharset()
            );

            self::$service = "CheckPreApproval";
            return self::getResult($connection, $notificationCode);

        } catch (PagSeguroServiceException $err) {
            throw $err;
        } catch (Exception $err) {
            LogPagSeguro::error("Exception: " . $err->getMessage());
            throw $err;
        }
    }


    /**
     * @param PagSeguroConnectionData $connection
     * @param $code
     * @return null|PagSeguroAuthorization|PagSeguroParserData|PagSeguroTransaction
     * @throws PagSeguroServiceException
     */
    private static function getResult($connection, $code)
    {
        $httpStatus = new PagSeguroHttpStatus($connection->getStatus());
        $response   = $connection->getResponse();

        switch ($httpStatus->getType()) {
            case 'OK':
                switch(self::$service) {
                    case "CheckPreApproval":
                        $response = PagSeguroPreApprovalParser::readPreApproval($response);
                        break;
                    case "CheckAuthorization":
                        $response = PagSeguroAuthorizationParser::readAuthorization($response);
                        break;
                    case "CheckTransaction":
                        $response = PagSeguroTransactionParser::readTransaction($response);
                        break;
                }
                //Logging
                $log['text'] = sprintf(
                    "PagSeguroNotificationService.%s(notificationCode=$code) - end ",
                    self::$service
                );
                $log['action'] = $response->toString();
                LogPagSeguro::info($log['text'] .$log['action'] . ")");

                break;
            case 'BAD_REQUEST':

                $errors = PagSeguroServiceParser::readErrors($connection->getResponse());
                $errors = new PagSeguroServiceException($httpStatus, $errors);
                //Logging
                $log['text'] = sprintf(
                    "PagSeguroNotificationService.%s(notificationCode=$code) - error ",
                    self::$service
                );
                LogPagSeguro::error($log['text'] . $errors->getOneLineMessage());
                //Exception
                throw $errors;

                break;
            default:
                $errors = new PagSeguroServiceException($httpStatus);
                //Logging
                $log['text'] = sprintf(
                    "PagSeguroNotificationService.%s(notificationCode=$code) - error ",
                    self::$service
                );
                LogPagSeguro::info($log['text'].$errors->getOneLineMessage());
                //Exception
                throw $errors;
                break;
        }
        return isset($response) ? $response : null;
    }
}
