<?php  // vim:set et ts=4 sw=4 sts=4:
# Copyright (C) 2003-2014 hipplay Inc.
#
# This is UNPUBLISHED PROPRIETARY SOURCE CODE OF hipplay Inc.
# The copyright notice above does not evidence any actual or intended
# publication of such source code. The contents of this file may not
# be disclosed to third parties, copied or duplicated in any form, in
# whole or in part, without the prior written permission of
# hipplay Inc.
#
namespace HipPlayConnect\REST;


use DOMDocument;
use HipPlayConnect\AxRecoverableErrorException;
use HipPlayConnect\AxUnrecoverableErrorException;

class AxRESTResponse
{
    
	protected $HSCode = null;              // HTTP status code or array of HipServ error codes
	protected $statusCode = null;          // HTTP status code
	protected $contentType;
	protected $body;
	private   $isError = false;
	
	protected static $statusMsg = array
	(
		200 => 'OK',						// Success w/ data to output
		201 => 'Created',					// Resource created
		204 => 'No Content',				// Success w/o data to output
		400 => 'Bad Request',				// malformed xml...
		401 => 'Unauthorized',				// Need to authenticate
		403 => 'Forbidden',					// legitimate request but cannot be completed at this point
		404 => 'Not Found',					// Resource does not exist
		405 => 'Method Not Allowed',		// HTTP method not allowed
		409 => 'Conflict',					// OK request but cannot be completed (duplicate file...)
		415 => 'Unsupported Media Type',	// wrong input content type
		500 => 'Internal Server Error'		// fatal error, failure
	);
	
	protected static $errorMsg = array
	(
		 AxRecoverableErrorException::ERR_ILLEGAL_FILENAME	=> 'Illegal Filename',
		 AxRecoverableErrorException::ERR_FILE_EXISTS	=> 'File Already Exists',
		 AxRecoverableErrorException::ERR_CANNOT_PARSE_XML	=> 'Cannot Parse XML',
		 AxUnRecoverableErrorException::ERR_IO_ERROR	=> 'I/O Error',
		 AxRecoverableErrorException::ERR_INVALID_PARAMETER	=> 'Invalid Parameter',
		 AxRecoverableErrorException::ERR_INVALID_EMAIL => 'Invalid Email',
		 AxRecoverableErrorException::ERR_SHARE_FROM_UNDEFINED => 'share_from_email setting is undefined',
		 AxRecoverableErrorException::ERR_ERROR_SENDING_EMAIL => 'Error sending email',
		 AxRecoverableErrorException::ERR_CANNOT_GET_AD => 'Cannot get ad',
		 AxRecoverableErrorException::ERR_DUPLICATE_EMAIL => 'Duplicate email',
		 AxRecoverableErrorException::ERR_CONTACT_DOESNT_EXIST => 'Contact does not exist',
		 AxRecoverableErrorException::ERR_CONTACT_USED_IN_ALBUMS => 'Contact is used in albums',
		 AxRecoverableErrorException::ERR_INVALID_LOGIN => 'Invalid login/password combination',
		 AxRecoverableErrorException::ERR_MUST_CHANGE_PASSWORD => 'Password must be changed',
		 AxRecoverableErrorException::ERR_RELEASE_MISMATCH => 'Client/Server Release Mismatch',
         AxRecoverableErrorException::ERR_CANNOT_RESET_PASSWORD => 'Cannot reset password, unknown email',
         AxRecoverableErrorException::ERR_SAVE_POSITION_UNSUPPORTED => 'Saved position not supported for this media type',
         AxRecoverableErrorException::ERR_KEYWORD_VALIDATION => 'At least one of the keywords must have 3 characters or more',
         AxRecoverableErrorException::ERR_3RD_PARTY_UNAUTHORIZED => 'User is not authorized/logged into the requested 3rd party service.', 
         AxRecoverableErrorException::ERR_3RD_PARTY_ERROR => 'Misc 3rd Party service error',
         AxRecoverableErrorException::ERR_3RD_PARTY_PHOTOSET => '3rd party photoset does not exist',
         AxRecoverableErrorException::ERR_INVALID_AUTH_CODE => 'Invalid Authentication Code',
         AxRecoverableErrorException::ERR_SELF_COPY => 'Cannot copy/move to self or to a descendant',
         AxRecoverableErrorException::ERR_BACKUP_FILE_SIZE => 'File too large to be backed up',
         AxRecoverableErrorException::ERR_BACKUP_STATUS_INHERITED => 'File inherits its scheduled storage operation, it cannot be changed',
         AxRecoverableErrorException::ERR_BACKUP_FILE_TYPE => 'Scheduled storage operation cannot be changed for a file with type discrepency',
         AxRecoverableErrorException::ERR_BACKUP_NOT_LOCAL => 'File does not exist on the HipServ, it cannot be scheduled for backup',   
         AxRecoverableErrorException::ERR_BACKUP_NOT_REMOTE => 'File does not exist remotely, it cannot be scheduled for removal',
         AxRecoverableErrorException::ERR_SERVICE_DISABLED => 'Service is disabled',
         AxRecoverableErrorException::ERR_CANNOT_CLEAR_JOBS => 'Cannot clear non-terminated jobs',
         AxRecoverableErrorException::ERR_CANNOT_CANCEL_JOBS => 'Cannot cancel terminated jobs',
         AxRecoverableErrorException::ERR_AGG_INVALID_REQUEST_URI => 'Request Aggregator: invalid request URI',
         AxRecoverableErrorException::ERR_AGG_NON_XML_RESPONSE => 'Request Aggregator: non-XML/UTF-8 response',
         AxRecoverableErrorException::ERR_BACKUP_NO_FILE => 'No file to backup/restore',
         AxRecoverableErrorException::ERR_ORANGE_ACCOUNT_NOT_BOUND => 'Orange account not bound',
         AxRecoverableErrorException::ERR_ORANGE_CANNOT_LOGON_MYCO => 'Cannot log on MyCo',
         AxRecoverableErrorException::ERR_ORANGE_MYCO_DOWN => 'MyCo down',
         AxRecoverableErrorException::ERR_ORANGE_NO_PHOTOPRINT_SESSION => 'No Photoprint session is open',
         AxRecoverableErrorException::ERR_ORANGE_AUTH_SERVER_UNAVAILABLE => 'Authorization server unavailable',
         AxRecoverableErrorException::ERR_ORANGE_AUTH_DENIED => 'Authorization denied',
         AxRecoverableErrorException::ERR_NO_FILE_TO_UPLOAD => 'No valid file to upload',
         AxRecoverableErrorException::ERR_SERVICE_UNAVAILABLE => 'Service Unavailable',
         AxRecoverableErrorException::ERR_FILE_TOO_LARGE => 'File too large',
         AxRecoverableErrorException::ERR_CANT_DELETE_SELF => 'Attempted to delete self',
         AxRecoverableErrorException::ERR_MYCO_ACCOUNT_NOT_ACTIVATED => 'MyCo account not activated',
         AxRecoverableErrorException::ERR_MAX_NB_USERS_REACHED => 'Maximum number of users reached',
         AxRecoverableErrorException::ERR_CONTACT_ALREADY_OWNED_BY_USER => 'User already has contact with this e-mail address',
         AxUnRecoverableErrorException::ERR_DISK_FULL  => 'Disk Full',
         AxRecoverableErrorException::ERR_FORMAT_USB => 'Format USB failed',
         AxRecoverableErrorException::ERR_RAID_REBUILD => 'Rebuild Failure: Generic',
         AxRecoverableErrorException::ERR_RAID_REBUILD_TYPE_UNSUPPORTED => 'Rebuild Failure: Unsupported Array Type (only for RAID1 and JBOD are supported)',
         AxRecoverableErrorException::ERR_RAID_FORMAT => 'Format Failure: Generic',
         AxRecoverableErrorException::ERR_RAID_FORMAT_UNAVAILABLE => 'Format Failure: Unavailable (Not enough hardware to perform, i.e. RAID0 with less than 2 drives)',
         AxRecoverableErrorException::ERR_RAID_FORMAT_TYPE_UNSUPPORTED => 'Format Failure: Unsupported Array Type (i.e. array type is not supported on this platform)',
         AxRecoverableErrorException::ERR_RAID_RECONFIGURE  => 'Reconfigure Failure: Generic',
         AxRecoverableErrorException::ERR_RAID_RECONFIGURE_UNAVAILABLE => 'Reconfigure Failure: Unavailable (Not enough hardware to perform, i.e. RAID0 with less than 2 drives)',
         AxRecoverableErrorException::ERR_RAID_RECONFIGURE_TYPE_UNSUPPORTED => 'Reconfigure Failure: Unsupported Array Type (i.e. array type is not supported on this platform)',
         AxRecoverableErrorException::ERR_WIRELESS_NO_ADAPTER => 'No Wireless Adapter',
         AxRecoverableErrorException::ERR_NO_DATABASE_FOUND => 'No Database',
	);

	public function __construct( $HSCode, $body = '', $contentType = null )
	{
        $this->HSCode = $this->statusCode = $HSCode;
        $this->body        = &$body;
        $this->contentType =  $contentType;
        
        // HipServ error codes
        if ( is_array( $HSCode ) ) {
            $this->statusCode = 200;
            $this->isError = true;
        }
            
        // Error (HTTP or HipServ)
        if ( $this->statusCode >= 400 )    
            $this->isError = true;
	}
	
	public function isError()
	{
	    return $this->isError;
	}
	
	public function getStatusCode()
	{
	    return $this->statusCode;
	}
	
	public function getContentTypeAndBody( $isFlexMode = false )
	{
        $HSCode = $this->HSCode;
        
        // in Flex mode, convert regular HTTP errors to the "array" format to output them as XML
        if ( $this->isError && $isFlexMode && !is_array( $HSCode ) )
            $HSCode = array( $HSCode );
         
        //
        // error to output as XML
        //
        if ( is_array( $HSCode ) ) {
            $doc = new DOMDocument( '1.0' );
            $root = $doc->appendChild( $doc->createElement( 'errors' ) );
            $i = 0;
            foreach ( $HSCode as $c ) {
                $error = $doc->createElement( 'error' );
                $error->setAttribute( 'code', $c );
                $error->setAttribute( 'msg', isset( self::$errorMsg[ $c ] ) ? self::$errorMsg[ $c ] : ( isset( self::$statusMsg[ $c ] ) ? self::$statusMsg[ $c ] : '' ) );
                
                // add details to error XML
                if ( is_array( $this->body ) && isset( $this->body[ $i ] ) && is_array( $this->body[ $i ] ) )
                    foreach ( $this->body[ $i ] as $key => $value )
                        $error->setAttribute( $key, $value );
                
                $root->appendChild( $error );
                $i++;
            }
            return array( 'text/xml; charset=UTF-8', $doc->saveXML() );
        }
	    
        // default (success or error not returned as XML): retun contentType and body as is
	    return array( $this->contentType, $this->body );
	}
	
	public function send()
	{
	    // In Flex mode, always return 200
		header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' ' . ( isset( $_GET[ 'method' ] ) ? 200: $this->statusCode ) . ' ' . self::$statusMsg[ $this->statusCode ] );
		list( $contentType, $body ) = $this->getContentTypeAndBody( isset( $_GET[ 'method' ] ) );
		if ( !is_null( $contentType ) )
			header( 'Content-Type: ' . $contentType );
		echo $body;
//        breakPoint( 'Process REST request' );        
		exit(1);
	}
}
