package com.insidesecure.drm.android.reference.entitlements;

import java.io.*;
import java.net.*;
import java.util.*;

import com.insidesecure.drmagent.*;
import com.insidesecure.drmagent.entitlements.*;

public class SamplePlayReadyEntitlementDelegate implements PlayReadyEntitlementDelegate
{

    @Override
    public DRMError acquireLicense(final DRMContent drmContent, final EntitlementRequest entitlementRequest, final EntitlementResponse entitlementResponse)
    {
        final Map<String, String> headers = new HashMap<>();
        headers.put(SOAP_ACTION_HEADER_NAME, SOAP_ACTION_HEADER_VALUE_ACQUIRE_LICENSE);
        headers.put(SOAP_ACTION_CONTENT_TYPE_HEADER_NAME , SOAP_ACTION_CONTENT_TYPE_HEADER_VALUE);
        return postRequest(entitlementRequest, entitlementResponse, headers);
    }

    @Override
    public DRMError acknowledgeLicense(final DRMContent drmContent, final EntitlementRequest entitlementRequest, final EntitlementResponse entitlementResponse)
    {
        final Map<String, String> headers = new HashMap<>();
        headers.put(SOAP_ACTION_HEADER_NAME, SOAP_ACTION_HEADER_VALUE_ACKNOWLEDGE_LICENSE);
        headers.put(SOAP_ACTION_CONTENT_TYPE_HEADER_NAME , SOAP_ACTION_CONTENT_TYPE_HEADER_VALUE);
        return postRequest(entitlementRequest, entitlementResponse, headers);
    }

    @Override
    public DRMError joinDomain(final EntitlementRequest entitlementRequest, final EntitlementResponse entitlementResponse)
    {
        final Map<String, String> headers = new HashMap<>();
        headers.put(SOAP_ACTION_HEADER_NAME, SOAP_ACTION_HEADER_VALUE_JOIN_DOMAIN);
        headers.put(SOAP_ACTION_CONTENT_TYPE_HEADER_NAME , SOAP_ACTION_CONTENT_TYPE_HEADER_VALUE);
        return postRequest(entitlementRequest, entitlementResponse, headers);
    }

    @Override
    public DRMError leaveDomain(final EntitlementRequest entitlementRequest, final EntitlementResponse entitlementResponse)
    {
        final Map<String, String> headers = new HashMap<>();
        headers.put(SOAP_ACTION_HEADER_NAME, SOAP_ACTION_HEADER_VALUE_LEAVE_DOMAIN);
        headers.put(SOAP_ACTION_CONTENT_TYPE_HEADER_NAME , SOAP_ACTION_CONTENT_TYPE_HEADER_VALUE);
        return postRequest(entitlementRequest, entitlementResponse, headers);
    }


    public DRMError getRequest (EntitlementRequest entitlementRequest, EntitlementResponse entitlementResponse, Map<String,String> headers)
    {
        long t1 = System.currentTimeMillis ();

        try
        {
            URL url = new URL ( entitlementRequest.getServerURL() );

            final HttpURLConnection connection = ( HttpURLConnection ) url.openConnection ();

            connection.setRequestMethod ( "GET" );
            connection.setDoInput ( true );
            connection.setDoOutput ( false );

            if (headers != null && !headers.isEmpty())
            {
                for ( Map.Entry<String, String> header : headers.entrySet () )
                {
                    connection.addRequestProperty (header.getKey(),header.getValue());
                }
            }

            connection.connect ();

            try
            {
                final int statusCode = connection.getResponseCode ();

                final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream ();
                final InputStream inputStream = connection.getInputStream ();
                try
                {
                    final int bufferLen = 16 * 1024;
                    final byte[] buffer = new byte[ bufferLen ];

                    int length = inputStream.read ( buffer, 0, bufferLen );
                    while ( length != -1 )
                    {
                        byteArrayOutputStream.write ( buffer, 0, length );
                        length = inputStream.read ( buffer, 0, bufferLen );
                    }

                    byteArrayOutputStream.flush ();
                    byteArrayOutputStream.close ();
                    entitlementResponse.setEntitlementResponseData (byteArrayOutputStream.toByteArray ());
                }
                finally
                {
                    inputStream.close ();
                }
            }
            finally
            {
                connection.disconnect ();
            }
        }
        catch (IOException e)
        {
            return DRMError.IO_ERROR;
        }
        catch ( Exception e )
        {
            return DRMError.IO_ERROR;
        }

        return DRMError.SUCCESS;
    }

    public DRMError postRequest (EntitlementRequest entitlementRequest, EntitlementResponse entitlementResponse, Map<String,String> headers)
    {
        boolean hasPostData = entitlementRequest.getEntitlementRequestData () != null;
        long t1 = System.currentTimeMillis ();

        try
        {
            URL url = new URL ( entitlementRequest.getServerURL () );

            HttpURLConnection connection = ( HttpURLConnection ) url.openConnection ();

            connection.setRequestMethod ( "POST" );
            connection.setDoInput ( true );
            connection.setDoOutput ( hasPostData );

            if (headers != null && !headers.isEmpty())
            {
                for ( Map.Entry<String, String> header : headers.entrySet () )
                {
                    connection.addRequestProperty (header.getKey(),header.getValue());
                }
            }

            connection.connect ();

            try
            {
                if (hasPostData)
                {
                    final OutputStream outputStream = connection.getOutputStream ();
                    outputStream.write ( entitlementRequest.getEntitlementRequestData () );
                    outputStream.flush ();
                    outputStream.close ();
                }


                final int statusCode = connection.getResponseCode ();

                final InputStream inputStream;
                switch (statusCode)
                {
                    case 200:
                    case 204:
                        inputStream = connection.getInputStream();
                        break;
                    // Special case for 500 errors - could be a special 'we need to join a domain' response
                    case 500:
                        inputStream = connection.getErrorStream();
                        break;
                    default:
                        return DRMError.IO_ERROR;
                }

                try
                {
                    final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

                    final int bufferLen = 16 * 1024;
                    final byte[] buffer = new byte[bufferLen];

                    int length = inputStream.read(buffer, 0, bufferLen);
                    while (length != -1)
                    {
                        byteArrayOutputStream.write(buffer, 0, length);
                        length = inputStream.read(buffer, 0, bufferLen);
                    }

                    byteArrayOutputStream.flush();
                    byteArrayOutputStream.close();
                    entitlementResponse.setEntitlementResponseData(byteArrayOutputStream.toByteArray());
                }
                finally
                {
                    inputStream.close();
                }

            }
            finally
            {
                connection.disconnect ();
            }
        }
        catch (IOException e)
        {
            return DRMError.IO_ERROR;
        }
        catch ( Exception e )
        {
            return DRMError.IO_ERROR;
        }

        return DRMError.SUCCESS;

    }


    @Override
    public void cancelEntitlementRequest()
    {
        
    }
}
