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

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>

//#include <db_config.h>
//#include <db_int.h>
#ifdef DB_UNKNOWN
#undef DB_UNKNOWN
#endif
#include "db.h"

#define ATTRIBUTENUM                            36
#define SEC_INDEX_NUM				3

#define MAX_NUMBER                              30

#define DICOM_HOME                              "dicom"

#define DB_FILE_NAME                            "dicom.db"
#define DICOM_DB_NAME                           "dicom"
#define PATIENT_NAME_SECONDARY_DB_NAME          "patient_name"
#define MODALITY_SECONDARY_DB_NAME              "modality"
#define ACQUISITION_DATE_SECONDARY_DB_NAME      "acquisition_time"

extern char atts_name[ATTRIBUTENUM][40];

enum ATT_INDEX {
    ACCESSIONNUMBER, 
    ACQUISITIONDATE, 
    ACQUISITIONTIME, 
    BODYPARTEXAMINED, 
    DATACOLLECTIONDIAMETER,
    DEVICESERIALNUMBER,
    DISTANCESOURCETODETECTOR,
    DISTANCESOURCETOPATIENT,
    IMAGECOMMENTS, 
    INSTITUTIONADDRESS,
    INSTITUTIONNAME, 
    INSTITUTIONALDEPARTMENTNAME, 
    KVP, 
    MANUFACTURER, 
    MANUFACTURERMODELNAME, 
    MODALITY, 
    NAMEOFPHYSICIANREADINGSTUDY, 
    OPERATORNAME,
    PATIENTAGE,
    PATIENTBIRTHDATE,
    PATIENTID,
    PATIENTNAME,
    PATIENTSEX,
    PERFORMINGPHYSICIANNAME,
    REFERRINGPHYSICIANNAME,
    SERIESDATE,
    SERIESINSTANCEUID,
    SLICETHICKNESS,
    SOFTWAREVERSION,
    SOPCLASSUID,
    SOPINSTANCEUID,
    SOURCETYPE,
    SPATIALRESOLUTION,
    STATIONNAME,
    STUDYDATE,
    STUDYDESCRIPTION
 };

enum SEC_INDEX {S_MDOFFSET, S_PNOFFSET, S_ADOFFSET};

/* Used to indicate a secondary index or a primary database */
enum DB_TYPE { SEC, PRI };

typedef struct _dicom_dbs{
        DB *ad_sdbp;              /* acquisition date (AD) secondary db */
        DB *dicom_dbp;                              /* DICOM primary db */
        DB *md_sdbp;                      /* modality (MD) secondary db */
        DB *pn_sdbp;                /* patient's name (PN) secondary db */

        const char      *ad_sdb_name;           /* AD secondary db name */
        const char      *dicom_db_name;         /* DICOM primary db name*/
        const char      *md_sdb_name;            /* MD secondary db name*/
        const char      *pn_sdb_name;            /* PN secondary db name*/

        const char      *home_dir;                    /* home directory */
        const char      *db_file_name;                  /* db file name */ 
}DICOM_DBS;


typedef struct _dicom_image{
	u_int32_t      id;

	u_int32_t       accession_number_length;    
	u_int32_t       acquisition_date_length;    
	u_int32_t       acquisition_time_length;    
	u_int32_t       body_part_examined_length;   
	u_int32_t       data_collection_diameter_length;   
	u_int32_t       device_serial_number_length;   
	u_int32_t       distance_source_to_detector_length;   
	u_int32_t       distance_source_to_patient_length; 
	u_int32_t       image_comments_length;    
	u_int32_t       institution_address_length;    
	u_int32_t       institution_name_length;    
	u_int32_t       institutional_department_name_length;    
	u_int32_t       kvp_length;    
	u_int32_t       manufacturer_length;    
	u_int32_t       manufacturer_model_name_length;    
	u_int32_t       modality_length;    
	u_int32_t       name_of_physician_reading_study_length;    
	u_int32_t       operator_name_length;   
	u_int32_t       patient_age_length;
	u_int32_t       patient_birth_date_length;   
	u_int32_t       patient_id_length;
	u_int32_t       patient_name_length;   
	u_int32_t       patient_sex_length;    
	u_int32_t       performing_physician_name_length;   
	u_int32_t       referring_physician_name_length;     
	u_int32_t       series_date_length;   
	u_int32_t       series_instance_uid_length;   
	u_int32_t       slice_thickness_length;
	u_int32_t       software_version_length; 
	u_int32_t       sop_class_uid_length;   
	u_int32_t       sop_instance_uid_length;   
	u_int32_t       source_type_length;   
	u_int32_t       spatial_resolution_length;   
	u_int32_t       station_name_length;   
	u_int32_t       study_date_length;  
	u_int32_t       study_description_length;   
        u_int32_t       thumbnail_format_length; /* Byte size of format */
        u_int32_t       thumbnail_content_length;
						/* Byte size of content */
	
	char            *accession_number;    
	char            *acquisition_date;    
	char            *acquisition_time;    
	char            *body_part_examined;   
	char            *data_collection_diameter;   
	char            *device_serial_number;   
	char            *distance_source_to_detector;   
	char            *distance_source_to_patient; 
	char            *image_comments;    
	char            *institution_address;    
	char            *institution_name;    
	char            *institutional_department_name;    
	char            *kvp;    
	char            *manufacturer;    
	char            *manufacturer_model_name;    
	char            *modality;    
	char            *name_of_physician_reading_study;    
	char            *operator_name;   
	char            *patient_age;
	char            *patient_birth_date;   
	char            *patient_id;
	char            *patient_name;   
	char            *patient_sex;    
	char            *performing_physician_name;   
	char            *referring_physician_name;     
	char            *series_date;   
	char            *series_instance_uid;   
	char            *slice_thickness;
	char            *software_version; 
	char            *sop_class_uid;   
	char            *sop_instance_uid;   
	char            *source_type;   
	char            *spatial_resolution;   
	char            *station_name;   
	char            *study_date;  
	char            *study_description;   
        char            *thumbnail_format;          /* thumbnail format */
        char            *thumbnail_content;        /* thumbnail content */		
}DICOM_IMAGE;

/* Function prototypes */
int close_dbs(DICOM_DBS *dm_dbs, DB_ENV *env);
void copy_dicom_image(DICOM_IMAGE *src_dicom_image, 
    DICOM_IMAGE *des_dicom_image);
void copy_memory(void *src_date, void *des_data, int length);
int convert_bytes_to_int(char *bytes);
int convert_int_to_bytes(int number, char *bytes);
WCHAR **convertCharToWchar(char *chars);
char **convertWcharToChar(WCHAR *wchars);
int delete_all_dicom(DICOM_DBS *dbs, DB_ENV *env, DB_TXN *txn, 
    DICOM_IMAGE *dicom_list, int *number);
int delete_dicom_with_id(DICOM_DBS *dbs, DB_ENV *env, DB_TXN *txn, int id,
    DICOM_IMAGE *dicom);
int find_attributes_index(char *name);
void free_dicom_image(DICOM_IMAGE *dicom_image);
void free_pointer(void *p);
void generate_file_name(int index, char *file_name, char *prefix, 
    char *suffix);
void get_dicom_image_from_dbt(DBT *data, DICOM_IMAGE *dicom_image);
int get_modality(DB *sdbp, const DBT *pkey, const DBT *pdata, DBT *skey);
int get_patient_name(DB *sdbp, const DBT *pkey, const DBT *pdata, 
    DBT *skey);
void initialize_dbs(DICOM_DBS *dm_dbs);
int open_db(DB **dbpp, const char *file_name, const char *db_name, 
    DB_ENV *env, u_int32_t access_mode, int is_secondary, DB_TXN *txn);	
int open_dbs(DICOM_DBS *dm_dbs, DB_ENV **envp, u_int32_t access_mode, 
    u_int32_t cache_size, u_int32_t log_size);
int open_env(DB_ENV **envp, u_int32_t cache_size, u_int32_t log_size, 
    const char *home_dir);
DBC *position_cursor(int s_att_index, char **value, DBC **cursorpp);
char *position_dicom_field(int att_index, DICOM_IMAGE *image, int *offset, 
    int *length);
int retrieve_all_dicom(DICOM_DBS *dbs, DB_ENV *env, DB_TXN *txn, 
    DICOM_IMAGE *dicom_image_list, int *number, int all);
int retrieve_key_with_cursor(DB_ENV *env, DBC *cursor, char** name, 
    int *number);
int retrieve_dicom_with_cursor(DBC *cursor, char * query, 
    DICOM_IMAGE *list,
    int *number);
int retrieve_dicom_with_dbp(DB *dbp, DB_TXN *txn, char *attribute, 
    char * query, DICOM_IMAGE *list, int *number);
int retrieve_dicom_with_multiple_attributes(DB_ENV *env, DB *dbp, 
    DBC **cursorpp, BOOL *isQueried, char **value, DICOM_IMAGE *list, 
    int *number);
int retrieve_dicom_with_id(DB *dbp, DB_ENV *env, DB_TXN *txn, int id, 
    DICOM_IMAGE *dicom);
int write_stream_into_bdb(char *stream, int length, DICOM_DBS *dbs, 
    DB_TXN *txn);
int partial_write(int id, char *stream, int doff, int original_length,
    int new_length, DB *dbp, DB_TXN *txn);
