/*******************************************************************************
 *  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.baselibs;

import java.io.IOException;

import cdac.medinfo.sdk.dcm30_04.commoninterface.IDicomStream;
import cdac.medinfo.sdk.dcm30_04.exceptions.InvalidDataTypeException;
import cdac.medinfo.sdk.dcm30_04.exceptions.InvalidValueException;
import cdac.medinfo.sdk.dcm30_04.exceptions.LengthLimitException;
import cdac.medinfo.sdk.dcm30_04.exceptions.OutOfMemoryException;
import cdac.medinfo.sdk.dcm30_04.exceptions.ValidationException;
import cdac.medinfo.sdk.dcm30_04.utils.DicomConfig;
import cdac.medinfo.sdk.dcm30_04.utils.DicomConstants;
import cdac.medinfo.sdk.dcm30_04.utils.DicomLogger;

import cdac.medinfo.sdk.dcm30_04.utils.StandardMethods;

/** 
 * UN is used to handle the DataTypes whose strcuture is not known. 
 * The UN DataType is used to hold the data in a byte buffer if the DataType is not known 
 */
public class UN extends DicomValue  
{
	

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	/**
	 * Creates an object of UN with default initialization 
	 */
	UN()
	{
		iVRType = DicomConstants.DCM_DT_UN;
	}

	/**
	 * Retrieves the max length for UL DataType
	 * @return long - max length for FD DataType
	 */
	public long getMaxLength()
	{
		return 0;
	}

	/**
	 * Reads the unknown data from the stream and stores it in a byte buffer
	 * 
	 * Note : It could throw OutOfMemoryException if length exceeds from allowed Heap Space. 
	 * @param objIDicomStream stream from which the DataType is to be written
	 * @param iUNLength length of the DicomValue to be read from the stream
	 * @return integer - returns status success/failure
	 * @throws InvalidDataTypeException If data type validation fails.
	 * @throws IOException If Input/Output operation fails.
	 */
	public boolean read(IDicomStream objIDicomStream,int iUNLength) throws InvalidDataTypeException, IOException
	{
		try
		{
			if(iUNLength > 0)
			{
				byte[] byteArray = new byte[iUNLength];
				objIDicomStream.readBuffer(byteArray);
				setValue(byteArray);
			}
			return true;
		}
		catch( OutOfMemoryError ome)
		{
			if(DicomConfig.createInstance().isLoggingOn())
			{
				DicomLogger.getLogger().log(ome.getMessage());
			}
			throw new OutOfMemoryException(StandardMethods.getStrVRtype(iVRType),ome);
		}
	}

	/**
	 * Writes the unknown data to the stream from the byte buffer
	 * This function writes the Data Value to the Stream
	 * @param objIDicomStream stream onto which the FD DataType is to serialized
	 * @return int - status indicating success/failure of write method
	 * @throws IOException If Input/Output operation fails.
	 */ 
	public int write(IDicomStream objIDicomStream) throws IOException
	{
		if(getValue() != null)
		{
			byte[] byteArray = (byte[])getValue();
			objIDicomStream.writeBuffer(byteArray, 0, byteArray.length);
		}
		return 1;
	}

	/**
	 * Validates UN DataType according to the rules specified in the DICOM Standard
	 * @param objValue instance of base Object class.
	 * @return boolean - status indicating success/failure of validation
	 * @throws InvalidValueException If dataType value validation fails.
	 * @throws LengthLimitException If value length exceeds the limit.
	 */	
	public boolean validate(Object objValue) throws InvalidValueException, LengthLimitException
	{
		return true;
	}

	/**
	 * Validates UN DataType according to the rules specified in the DICOM Standard
	 * @return boolean - status indicating success/failure of validation
	 * @throws InvalidValueException If dataType value validation fails.
	 * @throws LengthLimitException If value length exceeds the limit.
	 */	
	public boolean validate() throws InvalidValueException, LengthLimitException
	{
		return true;
	}

	/**
	 * Retrieves the actual value length of UL
	 * @return integer - actual value length of UN
	 */
	public int getValueLength()
	{
		if(value != null)
		{
			if(value instanceof byte[])
				return ((byte[])value).length;
		}

		return 0;
	}

	/**
	 * Sets the value in the DicomValue after performing validation on the value.
	 * After setting the value this method returns the errorcode indicating whether the validation of value was successful or failing 
	 * @param objValue value that is to be set into the DicomValue
	 * @throws InvalidDataTypeException If data type validation fails.
	 */
	/*
	 * This implementation of setValue will be used by Non-String Datatypes.
	 * For String datatypes there is a overridden implemention provided in DatatypeString Class
	 */
	public void setValue(Object objValue) throws InvalidDataTypeException
	{
		try
		{
			validate(objValue);
			/*
			 * This If-Else block checking whether given value is valid for this Type or not and sets VM according to that
			 */
			if((objValue != null) && (!(objValue instanceof byte[])))
				throw new InvalidValueException(StandardMethods.getStrVRtype(iVRType));

			value = objValue;
		}
		catch( InvalidValueException ive)
		{
			if(DicomConfig.createInstance().isLoggingOn())
			{
				DicomLogger.getLogger().log(ive.getMessage());
			}
			throw new InvalidDataTypeException(ive.getMessage(),ive);
		}
		catch( ValidationException ive)
		{
			if(DicomConfig.createInstance().isLoggingOn())
			{
				DicomLogger.getLogger().log(ive.getMessage());
			}
			throw new InvalidDataTypeException(ive.getMessage(),ive);
		}
	}

	/**
	 *  Dumps the value of Attribute as Hidden.
	 *  @param objIDicomStream - the Stream on which the Data is to be written.
	 *  @throws IOException - Exception is thrown indicating runtime failure of writing operation.
	 */
	public void dumpDICOMInfo(IDicomStream objIDicomStream) throws IOException
	{
		objIDicomStream.writeString("Value : " + "hidden");
	}
}
