// SMUTELEM.H
//
// Copyright (c) 1998 Symbian Ltd.  All rights reserved.
//



#if !defined (__SMUTELEM_H_)
#define __SMUTELEM_H_
#if !defined(__E32STD_H__)
#include <e32std.h>
#endif
#if !defined(__E32SBASE_H__)
#include <e32base.h>
#endif


class CDesC8ArrayFlat;
class RReadStream;
class RWriteStream;
class CCnvCharacterSetConverter;
struct TGsmTelNumber;

class TSmsOctet
	{
public:
	TSmsOctet(TInt aValue=0);
	inline operator TInt() const;
	const TSmsOctet& operator = (TInt aValue);
	inline void FillSemiOctets(TInt aNum);
	inline TInt SemiOctetsToNum();
	TUint8* EncodeL(TUint8* aPtr) const;
	const TUint8* DecodeL(const TUint8* aPtr);
	inline void InternalizeL(RReadStream& aStream);
	inline void ExternalizeL(RWriteStream& aStream) const;
protected:
	TUint8 iValue;
	};

class TSmsFirstOctet : public TSmsOctet
	{
public:
//  enums for first octet of all sms messages
	enum TSmsMTI
		{
		ESmsMTIDeliverOrDeliverReport=0x00,
		ESmsMTISubmitOrSubmitReport=0x01,
		ESmsMTIStatusReportOrCommand=0x02,

		ESmsMTIMask=0x03
		};
	enum TSmsUDHI   // Found in first octet of SmsSubmit and SmsDeliver and pssibly SmsSubmitReport and SmsDeliverReport
		{
		ESmsUDHIHeaderNotPresent=0x00,
		ESmsUDHIHeaderPresent=0x40,

		ESmsUDHIMask=0x40
		};
	enum TSmsReplyPath   // Found in first octet of SmsSubmit and SmsDeliver  
		{
		ESmsReplyPathNone=0x00,
		ESmsReplyPathExists=0x080,

		ESmsReplyPathMask=0x80
		};
//  Sms deliver
	enum TSmsMoreMessagesToSend
		{
		ESmsMoreMessagesToSend=0x00,
		ESmsNoMoreMessagesToSend=0x04,

		ESmsNoMoreMessagesToSendMask=0x04,
		};
	enum TSmsStatusReportIndicator
		{
		ESmsStatusReportNotReturned=0x00,
		ESmsStatusReportReturned=0x20,

		ESmsStatusReportIndicatorMask=0x20
		};
//  Sms submit
	enum TSmsRejectDuplicates
		{
		ESmsAcceptDuplicates=0x00,
		ESmsRejectDuplicates=0x04,

		ESmsRejectDuplicatesMask=0x04,
		};
	enum TSmsValidityPeriodFormat
		{
		ESmsVPFNone=0x00,
		ESmsVPFReserved=0x08,
		ESmsVPFInteger=0x10,
		ESmsVPFSemiOctet=0x18,

		ESmsVPFMask=0x18
		};
	enum TSmsStatusReportRequest
		{
		ESmsStatusReportNotRequested=0x00,
		ESmsStatusReportRequested=0x20,

		ESmsStatusReportRequestMask=0x20
		};
public:
	TSmsFirstOctet(TInt aValue=0);
	const TSmsFirstOctet& operator = (TInt aValue);
	};

class TSmsProtocolIdentifier : public TSmsOctet
	{
public:
	enum TSmsPIDType
		{
		ESmsPIDTelematicInterworking=0x00,
		ESmsPIDShortMessageType=0x40,
		ESmsPIDReserved=0x80,
		ESmsPIDSCSpecificUse=0xC0,

		ESmsPIDTypeMask=0xC0
		};
//  For interworking info
	enum TSmsTelematicDeviceIndicator
		{
		ESmsNoTelematicDevice=0x00,
		ESmsTelematicDevice=0x20,

		EPIDTelematicDeviceIndicatorMask=0x20
		};
	enum TSmsTelematicDeviceType
		{
		ESmsSCSpecificDevice=0x00,
		ESmsTelex=0x01,
		ESmsGroup3TeleFax=0x02,
		ESmsGroup4TeleFax=0x03,
		ESmsVoiceTelephone=0x04,
		ESmsERMES=0x05,
		ESmsNationalPagingSystem=0x06,
		ESmsVideotex=0x07,
		ESmsTeletexCarrierUnspecified=0x08,
		ESmsTeletexPSPDN=0x09,
		ESmsTeletexCSPDN=0x0A,
		ESmsTeletexAnaloguePSTN=0x0B,
		ESmsTeletexDigitalISDN=0x0C,
		ESmsUCI=0x0D,
		ESmsReserved1=0x0E,
		ESmsReserved2=0x0F,
		ESmsMessageHandlingFacility=0x10,
		ESmsX400MessageHandlingSystem=0x11,
		ESmsInternetElectronicMail=0x12,
		ESmsReserved3=0x13,
		ESmsReserved4=0x14,
		ESmsReserved5=0x15,
		ESmsReserved6=0x16,
		ESmsReserved7=0x17,
		ESmsSCSpecific1=0x18,
		ESmsSCSpecific2=0x19,
		ESmsSCSpecific3=0x1A,
		ESmsSCSpecific4=0x1B,
		ESmsSCSpecific5=0x1C,
		ESmsSCSpecific6=0x1D,
		ESmsSCSpecific7=0x1E,
		ESmsGsmMobileStation=0x1F,

		ESmsTelematicDeviceTypeMask=0x1F
		};
//  For no interworking info
	enum TSmsShortMessageALProtocol
		{
		ESmsShortMessageALProtocolMask=0x0F
		};
//  For short message type
	enum TSmsShortMessageType
		{
		ESmsShortMessageType0=0x00,
		ESmsReplaceShortMessageType1=0x01,
		ESmsReplaceShortMessageType2=0x02,
		ESmsReplaceShortMessageType3=0x03,
		ESmsReplaceShortMessageType4=0x04,
		ESmsReplaceShortMessageType5=0x05,
		ESmsReplaceShortMessageType6=0x06,
		ESmsReplaceShortMessageType7=0x07,
//  Reserved values
//		....
//		....
		ESmsReturnCallMesage=0x1F,
//  Reserved values
//		....
//		....
		ESmsMEDepersonalizationShortMessage=0x3E,
		ESmsSIMDataDownLoad=0x3F,

		ESmsShortMessageTypeMask=0x1F
		};
public:
	TSmsProtocolIdentifier();
	inline TSmsPIDType PIDType() const;
	TSmsTelematicDeviceIndicator TelematicDeviceIndicator() const;
	TSmsTelematicDeviceType TelematicDeviceType() const;
	TSmsShortMessageALProtocol ShortMessageALProtocol() const;
	TSmsShortMessageType ShortMessageType() const;
	};

class TSmsDataCodingScheme : public TSmsOctet
	{
public:
	enum TSmsDCSBits7To4
		{
		ESmsDCSTextUncompressedWithNoClassInfo=0x00,
		ESmsDCSTextUncompressedWithClassInfo=0x10,
		ESmsDCSTextCompressedWithNoClassInfo=0x20,
		ESmsDCSTextCompressedWithClassInfo=0x30,

		ESmsDCSReserved1=0x40,
		ESmsDCSReserved2=0x50,
		ESmsDCSReserved3=0x60,
		ESmsDCSReserved4=0x70,
		ESmsDCSReserved5=0x80,
		ESmsDCSReserved6=0x90,
		ESmsDCSReserved7=0xA0,
		ESmsDCSReserved8=0xB0,

		ESmsDCSMessageWaitingIndicationDiscardMessage=0xC0,

		ESmsDCSMessageWaitingIndication7Bit0xD0,  //  7 bit User data 
		ESmsDCSMessageWaitingIndicationUCS20xE0,  //  unicode User data 

		ESmsDCSTextUncompressed7BitOr8Bit=0xF0,

		ESmsDCSBits7To4Mask=0xF0
		};
	
	enum TSmsAlphabet
		{
		ESmsAlphabet7Bit=0x00,
		ESmsAlphabet8Bit=0x04,
		ESmsAlphabetUCS2=0x08,
		ESmsAlphabetReserved=0x0C,

		ESmsAlphabetMask=0x0C,
		};
	enum TSmsClass
		{
		ESmsClass0=0x00,
		ESmsClass1=0x01,
		ESmsClass2=0x02,
		ESmsClass3=0x03,

		ESmsClassMask=0x03,
		};
public:
	TSmsDataCodingScheme();
	TBool TextCompressed() const;
	void SetTextCompressed(TBool aCompressed);
	TSmsAlphabet Alphabet() const;
	void SetAlphabet(TSmsAlphabet aAlphabet);
	TBool Class(TSmsClass& aClass) const;
	void SetClass(TBool aClassDefined,TSmsClass aClass);
	};

class TSmsConvert
	{
public:
	virtual TUint8* EncodeL(TUint8* aPtr,const TDesC& aString)=0;
	virtual const TUint8* DecodeL(const TUint8* aPtr,TDes& aString)=0;
	virtual TBool IsSupported(TInt aChar) const=0;
	virtual TBool IsSymbol(TInt aChar) const=0;
	};

class TSms7BitConvert : public TSmsConvert
	{
public:
	TSms7BitConvert(CCnvCharacterSetConverter& aCharacterSetConverter);
	TUint8* EncodeL(TUint8* aPtr,const TDesC& aString);
	const TUint8* DecodeL(const TUint8* aPtr,TDes& aString);
	TBool IsSupported(TInt aChar) const;
	inline TBool IsSymbol(TInt aChar) const;
	inline void SetStartBit(TInt aStartBit);
private:
	CCnvCharacterSetConverter& iCharacterSetConverter;
	TInt iStartBit;
	};

class TSms8BitConvert : public TSmsConvert
	{
public:
	TSms8BitConvert(CCnvCharacterSetConverter& aCharacterSetConverter);
	TUint8* EncodeL(TUint8* aPtr,const TDesC& aString);
	const TUint8* DecodeL(const TUint8* aPtr,TDes& aString);
	TBool IsSupported(TInt aChar) const;
	inline TBool IsSymbol(TInt aChar) const;
private:
	CCnvCharacterSetConverter& iCharacterSetConverter;
	};

class TSmsUCS2Convert : public TSmsConvert
	{
public:
	TSmsUCS2Convert(CCnvCharacterSetConverter& aCharacterSetConverter);
	TUint8* EncodeL(TUint8* aPtr,const TDesC& aString);
	const TUint8* DecodeL(const TUint8* aPtr,TDes& aString);
	TBool IsSupported(TInt aChar) const;
	inline TBool IsSymbol(TInt aChar) const;
private:
	CCnvCharacterSetConverter& iCharacterSetConverter;
	};

class CSmsAddress : public CBase
	{
public:
	enum TSmsFirstBit
		{
		ESmsFirstBitMask=0x80
		};
	enum TSmsTypeOfNumber
		{
		ESmsTONUnknown=0x00,
		ESmsTONInternationalNumber=0x10,
		ESmsTONNationalNumber=0x20,
		ESmsTONNetworkSpecificNumber=0x30,
		ESmsTONSubscriberNumber=0x40,
		ESmsTONAlphaNumeric=0x50,
		ESmsTONAbbreviatedNumber=0x60,
		ESmsTONReserverved=0x70,

		ESmsTONMask=0x70
		};
	enum TSmsNumberingPlanIdentification
		{
		ESmsNPIUnknown=0x00,
		ESmsNPIISDNTelephoneNumberingPlan=0x01,
		ESmsNPIDataNumberingPlan=0x03,
		ESmsNPITelexNumberingPlan=0x04,
		ESmsNPINatiuonalNumberingPlan=0x08,
		ESmsNPIPrivateNumberingPlan=0x09,
		ESmsNPIERMESNumberingPlan=0x0A,
		ESmsNPIReservedForExtension=0x0F,

		ESmsNPIMask=0x0F
		};
public:
	static CSmsAddress* NewL(CCnvCharacterSetConverter& aCharacterSetConverter);
	~CSmsAddress();
	TPtrC Address() const;
	void SetAddressL(const TDesC& aAddress);
	void ParsedAddress(TGsmTelNumber& aParsedAddress) const;
	void SetParsedAddressL(const TGsmTelNumber& aParsedAddress);

	inline void SetTypeOfNumber(TSmsTypeOfNumber aTypeOfNumber);
	inline TInt TypeOfNumber() const;
	void SetNumberPlanIdentification(TSmsNumberingPlanIdentification aNumberingPlanIdentification);
	TInt NumberPlanIdentification() const;

	TUint8* EncodeL(TUint8* aPtr) const;
	const TUint8* DecodeL(const TUint8* aPtr);
	void InternalizeL(RReadStream& aStream);
	void ExternalizeL(RWriteStream& aStream) const;
private:
	CSmsAddress(CCnvCharacterSetConverter& aCharacterSetConverter);
	void NewBufferL(TInt aLength);	
	void DoSetParsedAddressL(const TDesC8& aAddress);
private:
	CCnvCharacterSetConverter& iCharacterSetConverter;
	TSmsOctet iTypeOfAddress;
	HBufC* iBuffer;	
	};

class TSmsServiceCenterTimeStamp
	{
public:
	enum {KSmsMaxTimeZoneNumQuarterHours=79};
	enum TSmsTimeZoneSignBit
		{
		ESmsTimeZonePositive=0x00,
		ESmsTimeZoneNegative=0x08,

		ESmsTimeZoneSignBitMask=0x08
		};
public:
	TSmsServiceCenterTimeStamp();
	void SetTimeOffset(TInt aNumQuarterHours);
	inline TInt TimeOffset() const;
	inline void SetTime(const TTime& aTime);
	inline const TTime& Time() const;
	TUint8* EncodeL(TUint8* aPtr) const;
	const TUint8* DecodeL(const TUint8* aPtr);
	void InternalizeL(RReadStream& aStream);
	void ExternalizeL(RWriteStream& aStream) const;
private:
	TTime iTime;
	TInt iTimeZoneNumQuarterHours;
	};

class TSmsValidityPeriod
	{
public:
	enum TValidityPeriodUnitInMinutes
		{
		EFiveMinutesInMinutes=5,
		EHalfAnHourInMinutes=30,
		EOneDayInMinutes=1440,
		EOneWeekInMinutes=7*EOneDayInMinutes
		};
	enum TValidityPeriodUnitStartInMinutes
		{
		ETwelveAndAHalfHoursInMinutes=25*EHalfAnHourInMinutes,
		ETwoDaysInMinutes=2*EOneDayInMinutes,
		EFiveWeeksInMinutes=5*EOneWeekInMinutes
		};
	enum TValidityPeriodStart
		{
		EHalfHourValidityPeriodStart=144,
		EDayValidityPeriodStart=168,
		EWeekValidityPeriodStart=197
		};
public:
	TSmsValidityPeriod(TSmsFirstOctet& aFirstOctet);
	inline TSmsFirstOctet::TSmsValidityPeriodFormat ValidityPeriodFormat() const;
	inline void SetValidityPeriodFormat(TSmsFirstOctet::TSmsValidityPeriodFormat aValidityPeriodFormat);
	inline void SetTimeIntervalMinutes(const TTimeIntervalMinutes& aTimeIntervalMinutes);
	inline const TTimeIntervalMinutes& TimeIntervalMinutes() const;
	TTime Time() const;
	TUint8* EncodeL(TUint8* aPtr) const;
	const TUint8* DecodeL(const TUint8* aPtr);
	void InternalizeL(RReadStream& aStream);
	void ExternalizeL(RWriteStream& aStream) const;
private:
	TSmsFirstOctet& iFirstOctet;
	TTimeIntervalMinutes iTimeIntervalMinutes;
	};

class CSmsInformationElement : public CBase
	{
public:
	enum TSmsInformationElementIdentifier
		{
		ESmsIEIConcatenatedShortMessages=0x00,
		ESmsIEISpecialSMSMessageIndication=0x01,
		ESmsIEIReserved=0x02,
		ESmsIEIValueNotUsed=0x03,
		ESmsIEIApplicationPortAddressing8Bit=0x04,
		ESmsIEIApplicationPortAddressing16Bit=0x05,
//  Reserved values
//		....
//		....
		ESmsIEISMEToSMESpecificUse1=0x80,
		ESmsIEISMEToSMESpecificUse2=0x81,
		ESmsIEISMEToSMESpecificUse3=0x82,
		ESmsIEISMEToSMESpecificUse4=0x83,
		ESmsIEISMEToSMESpecificUse5=0x84,
		ESmsIEISMEToSMESpecificUse6=0x85,
		ESmsIEISMEToSMESpecificUse7=0x86,
		ESmsIEISMEToSMESpecificUse8=0x87,
		ESmsIEISMEToSMESpecificUse9=0x88,
		ESmsIEISMEToSMESpecificUse10=0x89,
		ESmsIEISMEToSMESpecificUse11=0x8A,
		ESmsIEISMEToSMESpecificUse12=0x8B,
		ESmsIEISMEToSMESpecificUse13=0x8C,
		ESmsIEISMEToSMESpecificUse14=0x8D,
		ESmsIEISMEToSMESpecificUse15=0x8E,
		ESmsIEISMEToSMESpecificUse16=0x8F,
		ESmsIEISMEToSMESpecificUse17=0x90,
		ESmsIEISMEToSMESpecificUse18=0x91,
		ESmsIEISMEToSMESpecificUse19=0x92,
		ESmsIEISMEToSMESpecificUse20=0x93,
		ESmsIEISMEToSMESpecificUse21=0x94,
		ESmsIEISMEToSMESpecificUse22=0x95,
		ESmsIEISMEToSMESpecificUse23=0x96,
		ESmsIEISMEToSMESpecificUse24=0x97,
		ESmsIEISMEToSMESpecificUse25=0x98,
		ESmsIEISMEToSMESpecificUse26=0x99,
		ESmsIEISMEToSMESpecificUse27=0x9A,
		ESmsIEISMEToSMESpecificUse28=0x9B,
		ESmsIEISMEToSMESpecificUse29=0x9C,
		ESmsIEISMEToSMESpecificUse30=0x9D,
		ESmsIEISMEToSMESpecificUse31=0x9E,
		ESmsIEISMEToSMESpecificUse32=0x9F,
//  Reserved values
//		....
//		....
		ESmsIEISCSpecificUse1=0xC0,
		ESmsIEISCSpecificUse2=0xC1,
		ESmsIEISCSpecificUse3=0xC2,
		ESmsIEISCSpecificUse4=0xC3,
		ESmsIEISCSpecificUse5=0xC4,
		ESmsIEISCSpecificUse6=0xC5,
		ESmsIEISCSpecificUse7=0xC6,
		ESmsIEISCSpecificUse8=0xC7,
		ESmsIEISCSpecificUse9=0xC8,
		ESmsIEISCSpecificUse10=0xC9,
		ESmsIEISCSpecificUse11=0xCA,
		ESmsIEISCSpecificUse12=0xCB,
		ESmsIEISCSpecificUse13=0xCC,
		ESmsIEISCSpecificUse14=0xCD,
		ESmsIEISCSpecificUse15=0xCE,
		ESmsIEISCSpecificUse16=0xCF,
		ESmsIEISCSpecificUse17=0xD0,
		ESmsIEISCSpecificUse18=0xD1,
		ESmsIEISCSpecificUse19=0xD2,
		ESmsIEISCSpecificUse20=0xD3,
		ESmsIEISCSpecificUse21=0xD4,
		ESmsIEISCSpecificUse22=0xD5,
		ESmsIEISCSpecificUse23=0xD6,
		ESmsIEISCSpecificUse24=0xD7,
		ESmsIEISCSpecificUse25=0xD8,
		ESmsIEISCSpecificUse26=0xD9,
		ESmsIEISCSpecificUse27=0xDA,
		ESmsIEISCSpecificUse28=0xDB,
		ESmsIEISCSpecificUse29=0xDC,
		ESmsIEISCSpecificUse30=0xDD,
		ESmsIEISCSpecificUse31=0xDE,
		ESmsIEISCSpecificUse32=0xDF,
		};
public:
	static CSmsInformationElement* NewL(TSmsInformationElementIdentifier aIdentifier,const TDesC8& aData);
	static CSmsInformationElement* NewL();
	~CSmsInformationElement();

	inline TInt Identifier() const;
	TPtr8 Data();
	
	TUint8* EncodeL(TUint8* aPtr) const;
	const TUint8* DecodeL(const TUint8* aPtr);
	void InternalizeL(RReadStream& aStream);
	void ExternalizeL(RWriteStream& aStream) const;
private:
	CSmsInformationElement(TSmsInformationElementIdentifier aInformationElementIdentifier);
	void ConstructL(const TDesC8& aData);
	void NewDataL(TInt aLength);
private:
	TSmsOctet iIdentifier;
	HBufC8* iData;
	};

class CSmsUserData : public CBase
	{
public:
	enum {KSmsMaxUserDataSize=140};

public:
	static CSmsUserData* NewL(CCnvCharacterSetConverter& aCharacterSetConverter,TSmsFirstOctet& aFirstOctet,const TSmsDataCodingScheme& aDataCodingScheme);
	~CSmsUserData();

	inline TInt NumInformationElements() const;
	CSmsInformationElement& InformationElement(TInt aIndex) const;
	void AddInformationElementL(CSmsInformationElement::TSmsInformationElementIdentifier aIdentifier,const TDesC8& aData);
	void RemoveInformationElement(TInt aIndex);

	TInt MaxBodyLengthInChars() const;
	TPtrC Body() const;
	void SetBodyL(const TDesC& aBody);

	TBool IsSupported(TInt aChar) const;
	TBool IsSymbol(TInt aChar) const;

	TUint8* EncodeL(TUint8* aPtr) const;
	const TUint8* DecodeL(const TUint8* aPtr);
	void InternalizeL(RReadStream& aStream);
	void ExternalizeL(RWriteStream& aStream) const;
private:
	CSmsUserData(CCnvCharacterSetConverter& aCharacterSetConverter,TSmsFirstOctet& aFirstOctet,const TSmsDataCodingScheme& aDataCodingScheme);
	void ConstructL();
	TInt HeaderLength() const;
	TInt TotalHeaderLengthInUDLUnits() const;
	TInt BodyLengthInUDLUnits() const;
	void NewBodyL(TInt aLengthInChars);
	const TUint8*  DecodeBodyL(const TUint8* aPtr,TSmsConvert& aConvert,TInt aLength);
	TBool HeaderPresent() const;	
	void SetHeaderPresent(TBool aHeaderPresent);	

private:
	CCnvCharacterSetConverter& iCharacterSetConverter;

	TSmsFirstOctet& iFirstOctet;
	const TSmsDataCodingScheme& iDataCodingScheme;
	CArrayPtrFlat<CSmsInformationElement> iInformationElementArray;
	HBufC* iBody;
	};

#include "smutelem.inl"

#endif // !defined __SMUTELEM_H_
