/* Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. */

#include "stdafx.h"
#include "DicomService.h"

DicomService::DicomService()
{
        // Buffer to cache DICOM stream from HTTP body.
	m_buffer = NULL;
}

DicomService::~DicomService()
{
	// Close all internet handles.
	if (m_openHandle != NULL)
		InternetCloseHandle(m_openHandle);
	if (m_connHandle != NULL)
		InternetCloseHandle(m_connHandle);
	if (m_resHandle != NULL)
		InternetCloseHandle(m_resHandle);
	
	// Free buffer memory if it is not released. 
	if (m_buffer != NULL)
		free(m_buffer);
}

int DicomService::Download(DICOM_DBS *dbs)
{
	DWORD dwStartPos = 0;
	DWORD dwCurrentPos = 0;
	DWORD dwBufferReadBytes = 0;
	DWORD dwDicomReadBytes = 0;
	DWORD dwDicomContentAmount = 0;
	DWORD dwAvailableLen = 0;
	int ret;
	int dicomAmount = 0;

	// Initializes Internet functions. 
	m_openHandle = InternetOpen(TEXT("BDBClient"),  
                                    INTERNET_OPEN_TYPE_DIRECT, 
                                    NULL, NULL, 0);

	// Set up HTTP connection to server with specified port, autherized 
        // name and password.
	m_connHandle = InternetConnect(m_openHandle, 
                                       TEXT("10.182.114.155"), 
                                       8080, 
                                       TEXT("oracle"), 
                                       TEXT("welcome"),
                                       INTERNET_SERVICE_HTTP, 
                                       INTERNET_FLAG_KEEP_CONNECTION,
                                       0);

	// Open HTTP request, specified verb "GET" and URI "/". 
	m_resHandle = HttpOpenRequest(m_connHandle, TEXT("GET"),
                                      TEXT("/"),
                                      NULL, NULL, NULL, 
                                      INTERNET_FLAG_RELOAD, 0);

	// Send the request. 
	if (HttpSendRequest(m_resHandle, NULL, 0, NULL, 0) == false)
		return dicomAmount;

	// Malloc a buffer to cache one DICOM from HTTP responce stream and 
        // recycle the buffer to load all DICOMs. The buffer size should not
        // be smaller than any DICOM in the responce stream.
	m_buffer = (char*)malloc(sizeof(char) * BUFFER_SIZE); 
	memset(m_buffer, 0, BUFFER_SIZE);
	
	// Recieve DICOMs from HTTP responce stream and write them into BDB.
        // The responce steam is composed of sequenced DICOMs with its size 
        // prefixed. Everytime parse responce stream to retrieve a single
        // DICOM, get its size and write it into bdb. Iteratively store all
        // DICOM into bdb. 
        while (InternetQueryDataAvailable(m_resHandle, &dwAvailableLen, 
	    0, 0)) {
                // If there is no more data, quite the loop. 
                if (dwAvailableLen == 0)
                        break;

                // If there is no enough space for all available data to 
                // cache the buffer, those part that could be able to filled
                // in the buffer would be read. Unless, fill all into the 
		// buffer. 
                if (dwCurrentPos + dwAvailableLen > BUFFER_SIZE) 
                        InternetReadFile(m_resHandle, 
			    m_buffer + dwCurrentPos, 
                            BUFFER_SIZE - dwCurrentPos, 
			    &dwBufferReadBytes);
	     else 
                        InternetReadFile(m_resHandle, 
			    m_buffer + dwCurrentPos, 
                            dwAvailableLen, 
			    &dwBufferReadBytes);
	     
                // If no data is read, retry. 
                if (dwBufferReadBytes == 0) {
			Sleep(1000);
			continue;
		}

                // The current position is updated to the next available 
                // byte in the buffer. 
		dwCurrentPos = dwCurrentPos + dwBufferReadBytes;

                // Before loading a new DICOM, count its size first. The  
                // size is an integer represented by 4 bytes prefixed before
                // data. 
                if (dwDicomContentAmount == 0) 
                        dwDicomContentAmount = convert_bytes_to_int(
                            m_buffer + dwStartPos % BUFFER_SIZE) + 4;

                // Update how many bytes of the current DICOM have been 
		// read. 
                dwDicomReadBytes += dwBufferReadBytes;
	    
                // After got all bytes of the current DICOM, write the DICOM
                // into bdb. Then update position pointers. 
                if (dwDicomContentAmount <= dwDicomReadBytes && 
                    dwDicomContentAmount != 0) {
                        ret = write_stream_into_bdb(m_buffer + 
                            (dwStartPos + 4) % BUFFER_SIZE, 
                            dwDicomContentAmount - 4, dbs);
                        if (ret < 0)
                                return -1;
                        else if (ret == 0)
                                continue;
        
        		// Re-count the read byte for the next DICOM.
        		dwDicomReadBytes -= dwDicomContentAmount;
        		
        		// Clear the content size for next DICOM. 
        		dwDicomContentAmount = 0;
                        	
        		// Update the starting position for the next DICOM 
			//in buffer.
        		dwStartPos = (dwCurrentPos - dwDicomReadBytes) 
                            % BUFFER_SIZE;
        		
        		// Increase received DICOM number. 
        		dicomAmount++;
                }   
	}
	

	// Free the buffer.
	free(m_buffer);
	m_buffer = NULL;

	// Return the number of received DICOMs. 
	return dicomAmount;
}
