Function Picture_API(@API)
/***********************************************************************************************************************

    This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
    permission from SRP Computer Solutions, Inc.

    Name        :   Picture_API

    Description :   API logic for the Picture resource.

    Notes       :   All web APIs should include the API_SETUP insert. This will provide several useful variables:

                        HTTPMethod              - The HTTP Method (Verb) submitted by the client (e.g., GET, POST, etc.)
                        APIURL                  - The URL for the API entry point (e.g., api.mysite.com/v1).
                        FullEndpointURL         - The URL submitted by the client, including query params.
                        FullEndpointURLNoQuery  - The URL submitted by the client, excluding query params.
                        ParentURL               - The URL path preceeding the current endpoint.
                        CurrentAPI              - The name of this stored procedure.    

    Parameters  :
        API             [in] -- Web API to process. Format is [APIPattern].[HTTPMethod]:
                                    - APIPattern must follow this structure <Resource>[.ID.[<Property>]]
                                    - HTTPMethod can be any valid HTTP method, e.g., GET, POST, PUT, DELETE, etc.
                                Examples:
                                    - Picture.POST
                                    - Picture.ID.PUT
                                    - Picture.ID.firstName.GET
        Response       [out] -- Response to be sent back to the Controller (HTTP_MCP) or requesting procedure. Web API
                                services do not rely upon anything being returned in the response. This is what the
                                various services like SetResponseBody and SetResponseStatus services are for. A response
                                value is only helpful if the developers want to use it for debug purposes.

    History     :   (Date, Initials, Notes)
        11/19/18    dmb     Original programmer.
        01/23/20    dmb     [SRPFW-296] Add matching HEAD APIs for all GET APIs.

***********************************************************************************************************************/

#pragma precomp SRP_PreCompiler

$insert APP_INSERTS
$insert API_SETUP
$insert HTTP_INSERTS
$insert CONTACTS_EQUATES

PictureFolder   = '\WebAppData\ContactPictures\'

GoToAPI else
    // The specific resource endpoint doesn't have a API handler yet.
    HTTP_Services('SetResponseStatus', 204, 'This is a valid endpoint but a web API handler has not yet been created.')
end

Return Response OR ''


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Endpoint Handlers
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

API picture.GET
API picture.HEAD

    // Get the picture's physical file path from the CONTACT database row.
    KeyID           = ParentSegment
    PicturePath     = Drive() : HTTP_Resource_Services('GetColumnValues', 'CONTACTS', 'picture', KeyID)

    If PicturePath NE '' then
        // Verify the picture actually exists.
        If Dir(PicturePath) NE '' then
            // Get the image extension.
            ImageExt    = PicturePath[-1, 'B.']
            If ImageExt _EQC 'jpg' then ImageExt = 'jpeg'
            // Get the best content type that matches the client's and server's ability.
            ContentType = HTTP_Services('GetBestContentNegotiation', 'Accept', 'text/plain' : @FM : 'image/' : ImageExt)
            If ContentType NE '' then
                OSRead PictureBinary from PicturePath then
                    Begin Case
                        Case ContentType _EQC 'text/plain'
                            PictureBody = SRP_Encode(PictureBinary, 'BASE64')
                            PictureBody = 'data:' : 'image/' : ImageExt : ';base64,' : PictureBody
                            HTTP_Services('SetResponseHeaderField', 'Content-Encoding', 'base64')
                            HTTP_Services('SetResponseBody', PictureBody, False$, 'text/plain')

                        Case ContentType[1, 6] _EQC 'image/'
                            HTTP_Services('SetResponseBody', PictureBinary, True$, ContentType)

                    End Case
                end else
                    HTTP_Services('SetResponseError', '', '', 404, 'Picture for contact ' : KeyID : ' does not exist.', FullEndpointURL)
                end
            end
        end else
            HTTP_Services('SetResponseError', '', '', 404, 'Picture for contact ' : KeyID : ' does not exist.', FullEndpointURL)
        end
    end else
        HTTP_Services('SetResponseError', '', '', 404, 'Picture for contact ' : KeyID : ' does not exist.', FullEndpointURL)
    end

end api


API picture.PUT

    KeyID           = ParentSegment
    TableName       = 'CONTACTS'

    ContentType = HTTP_Services('GetHTTPContentType')

    If ContentType EQ '' OR ContentType _EQC 'text/plain' then
        Open TableName to hTable then
            Lock hTable, KeyID then
                ResponseStatus  = 200       ; // Updating an existing resource.
                Read DataRow from hTable, KeyID else
                    DataRow         = ''
                    ResponseStatus  = 201   ; // Creating a new resource.
                end

                // A URI scheme of the Base64 encoded image will be in the Data variable.
                HTTPPostString  = HTTP_Services('GetHTTPPostString')
                HTTPPostString  = HTTP_Services('DecodePercentString', HTTPPostString)
                Scheme          = HTTPPostString[1, 'F:']
                If Scheme _EQC 'data' then
                    MediaType   = HTTPPostString[Col2() + 1, 'F;']                  ; // Should be "image/png" or "image/jpg"
                    Encoding    = HTTPPostString[Col2() + 1, 'F,']                  ; // Should be "base64"
                    EncodedData = HTTPPostString[Col2() + 1, Len(HTTPPostString)]   ; // Should be the actual Base64 encoded content.
                    DecodedData = SRP_Decode(EncodedData, 'BASE64')
                    FileType    = MediaType[-1, 'B/']
                    FileName    = KeyID : '.' : FileType
                    FilePath    = Drive() : PictureFolder : FileName
                    Status()    = 0
                    OSWrite DecodedData to FilePath
                    StatusCode = Status()
                    If StatusCode then
                        Begin Case
                            Case StatusCode EQ 1    ; Error = 'Bad OS filename. Code: ' : StatusCode
                            Case StatusCode EQ 2    ; Error = 'Access denied by operating system. Code: ' : StatusCode
                            Case StatusCode EQ 3    ; Error = 'Disk or directory full. Code: ' : StatusCode
                            Case StatusCode EQ 4    ; Error = 'File does not exist. Code: ' : StatusCode
                            Case StatusCode EQ 5    ; Error = 'Unknown error. Code: ' : StatusCode
                            Case StatusCode EQ 6    ; Error = 'Attempt to write to read-only file. Code: ' : StatusCode
                            Case Otherwise$         ; Error = 'Unknown error. Code: ' : StatusCode
                        End Case
                        HTTP_Services('SetResponseError', '', '', 501, Error, FullEndpointURL)
                    end else
                        DataRow<CONTACTS_PICTURE$>  = PictureFolder : FileName
                        Write DataRow to hTable, KeyID then
                            HTTP_Services('SetResponseStatus', ResponseStatus)
                            HTTP_Services('SetResponseHeaderField', 'Content-Location', FullEndpointURL)
                        end else
                            HTTP_Services('SetResponseError', '', '', 500, 'Error writing ' : KeyID : ' to the ' : TableName : ' table.', FullEndpointURL)
                        end
                    end
                end else
                    HTTP_Services('SetResponseError', '', '', 415, '', FullEndpointURL)
                end
                Unlock hTable, KeyID else Null
            end else
                HTTP_Services('SetResponseError', '', '', 423, KeyID : ' is currently locked.', FullEndpointURL)
            end
        end else
            HTTP_Services('SetResponseError', '', '', 500, 'Error opening the ' : TableName : ' table.', FullEndpointURL)
        end
    end else
        HTTP_Services('SetResponseError', '', '', 415, 'Content-Type ' : ContentType : ' is not supported. Must specify "text/plain" or nothing.', FullEndpointURL)
    end

end api
