/*******************************************************************************
 *  Copyright 2017-2018 Centre for Development of Advanced Computing(C-DAC), Pune
 *  
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *  
 *   http://www.apache.org/licenses/LICENSE-2.0
 *  
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *******************************************************************************/
package cdac.medinfo.sdk.dcm30_04.services.spss.dbhelper;

import java.io.IOException;
import java.lang.reflect.Array;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import cdac.medinfo.sdk.dcm30_04.baselibs.DataSet;
import cdac.medinfo.sdk.dcm30_04.baselibs.DicomV3Factory;
import cdac.medinfo.sdk.dcm30_04.baselibs.ExplicitDE;
import cdac.medinfo.sdk.dcm30_04.baselibs.ImplicitDE;
import cdac.medinfo.sdk.dcm30_04.baselibs.SQ;
import cdac.medinfo.sdk.dcm30_04.baselibs.Tag;
import cdac.medinfo.sdk.dcm30_04.commoninterface.IDataElement;
import cdac.medinfo.sdk.dcm30_04.commoninterface.IDataSet;
import cdac.medinfo.sdk.dcm30_04.commoninterface.IDataTypeSQ;
import cdac.medinfo.sdk.dcm30_04.commoninterface.IDicomValue;
import cdac.medinfo.sdk.dcm30_04.commoninterface.IDictionaryReader;
import cdac.medinfo.sdk.dcm30_04.commoninterface.IItem;
import cdac.medinfo.sdk.dcm30_04.commoninterface.ITag;
import cdac.medinfo.sdk.dcm30_04.commoninterface.ITransferSyntax;
import cdac.medinfo.sdk.dcm30_04.exceptions.ParseException;
import cdac.medinfo.sdk.dcm30_04.services.dicomnetcommons.DataTypeConvertor;
import cdac.medinfo.sdk.dcm30_04.services.dimsecommons.DicomMessage;
import cdac.medinfo.sdk.dcm30_04.utils.DicomConstants;

import cdac.medinfo.sdk.dcm30_04.utils.ICollectionIterator;
import cdac.medinfo.sdk.dcm30_04.utils.ISingleCollection;
import cdac.medinfo.sdk.dcm30_04.utils.SingleCollection;
import cdac.medinfo.sdk.dcm30_04.utils.StandardMethods;


/**
 * In this class, the queries for the database are written.
 * @author samta
 *
 */


public class SPSS_DBQuery {

	
	/**
	 * Thid is default constructor for SPSS_DBQuery.
	 */
	public SPSS_DBQuery() {
		super();
	}

	private Connection objcon = null;
	//This set used in recursive method for retrieving matching DATASETUUIDs in Sequence.
	private Set<String> setIntersectedDatasetUIDList;// = new TreeSet<String>();

	Map<String,Integer> hs = new HashMap<String, Integer>();

	/**
	 * Sets Connection Object for used for querying Database.
	 * @param objcon object of Connection
	 */
	void setConnection(Connection objcon)
	{
		this.objcon = objcon;
	}
	
	boolean storeInstanceInfo(IDataSet objIDataSet)throws SQLException
	{
		objcon.setAutoCommit(false);
		String strDatasetUUID = StandardMethods.generateUUID(); 

		//String strValue = null;
		int iGroupNo,iElementNo,iVRType;
		for(IDataElement objDataElement : objIDataSet)
		{
			/*
			 * This If-Else block inserts DataElements in database.
			 * It inserts all first level data elements and for SQ element it inserts that SQ element and all item elements belonging to that SQ.  
			 */
			String strValue = null;
			IDicomValue objIDicomValue = objDataElement.getDicomValue();
			iGroupNo = objDataElement.getTag().getGroupNumber();
			iElementNo = objDataElement.getTag().getElementNumber();
			iVRType = objIDicomValue.getIVRType();
			if(!(objIDicomValue instanceof SQ))
			{
				if(objIDicomValue.getValue() != null)
					strValue = DataTypeConvertor.dicomDatatoString(objIDicomValue);
				insertInstanceInfo(strDatasetUUID,iGroupNo ,iElementNo , false, null, strValue, null, null,0, iVRType);
			}
			else
			{
				String strSQId = StandardMethods.generateUUID();
				insertInstanceInfo(strDatasetUUID,iGroupNo ,iElementNo , true, null, null, strSQId, null, 0, iVRType);
				insertSQInfo(objIDicomValue,strDatasetUUID,strSQId,null,1);
			}
		}
		objcon.commit();
		objcon.setAutoCommit(true);

		return true;

	}


	/**
	 * Inserts DataElement of a sequence and all its Items.
	 */
	private boolean insertSQInfo(IDicomValue objIDicomValue,String strDatasetUID,String strSQUUid,String strParentSQID,int iDELevel)throws SQLException
	{
		SQ objSQDicomData = (SQ)objIDicomValue;
		ICollectionIterator<IItem> objSQItemIterator = objSQDicomData.iterator();
		String strValue = null;
		while(objSQItemIterator.hasNext())
		{
			/*
			 * Iterating over Items of provided sequence and inserting DataElements which are not SQ.
			 * for SQ it recursively calls itself with changed SQUUID and ParentSQID.
			 * A sequence and all 
			 */
			IItem objItem = objSQItemIterator.next();
			String strItemUUID = StandardMethods.generateUUID();
			int iGroupNo,iElementNo,iVRType;
			ICollectionIterator<IDataElement> objDEIterator = objItem.iterator();
			while(objDEIterator.hasNext())
			{
				IDataElement objDataElement = objDEIterator.next();
				IDicomValue objTempDicomData = objDataElement.getDicomValue();
				iGroupNo = objDataElement.getTag().getGroupNumber();
				iElementNo = objDataElement.getTag().getElementNumber();
				iVRType = objTempDicomData.getIVRType();
				if(!(objTempDicomData instanceof SQ))
				{
					if(objTempDicomData.getValue() != null)
						strValue = DataTypeConvertor.dicomDatatoString(objTempDicomData);
					insertInstanceInfo(strDatasetUID,iGroupNo,iElementNo, false, strParentSQID, strValue, strSQUUid, strItemUUID, iDELevel, iVRType);
				}
				else
				{
					String strSQId = StandardMethods.generateUUID();
					insertInstanceInfo(strDatasetUID,iGroupNo,iElementNo, true, strSQUUid, null, strSQId,strItemUUID, iDELevel, iVRType);
					insertSQInfo(objTempDicomData,strDatasetUID,strSQId,strSQUUid,++iDELevel);
				}
			}
		}
		return true;
	}

	/**
	 * Inserts the information of DataElement in Database
	 */
	private boolean insertInstanceInfo(String strDatasetUUID,int iGroupNumber,int iElementNumber,boolean isSQ,String strParentSQID,String strValue,
			String strSQID,String strItemID,int iDELevel,int iDEVR)throws SQLException
			{
		String strQuery = "insert into SPSS_DEINFO(DEROWID,DATASETUUID,GROUPNUMBER,ELEMENTNUMBER,ISSQ,PARENTSQUID,VALUE,SQUUID,ITEMUUID,DELEVEL,DEVR) " +
				"values(?,?,?,?,?,?,?,?,?,?,?)";

		PreparedStatement ps = objcon.prepareStatement(strQuery);
		ps.setString(1,StandardMethods.generateUUID());
		ps.setString(2, strDatasetUUID);
		ps.setInt(3,iGroupNumber);
		ps.setInt(4,iElementNumber);
		if(isSQ)
			ps.setInt(5, 1);
		else
			ps.setInt(5, 0);
		ps.setString(6,strParentSQID);
		ps.setString(7, strValue);
		ps.setString(8,strSQID);
		ps.setString(9,strItemID);
		ps.setInt(10,iDELevel);
		ps.setInt(11,iDEVR);
		ps.executeUpdate();
		return true;
			}

}
