package cz.muni.fi.lasaris.sbms.data.providers.bacnet;

import cz.muni.fi.lasaris.sbms.data.entities.Address;
import cz.muni.fi.lasaris.sbms.data.providers.bacnet.util.MutableInteger;

public class BACnetAddress {
	
	private int instance;
	private int property;
	private int device;
	private int type;
	
	private Address address;
	
	public Address getAddress() {
		return address;
	}

	public BACnetAddress(Address dataPoint) {
		this.address = dataPoint;
		String a = dataPoint.getId(false);
		
		String[] parts = a.split("\\.");
		device = Integer.parseInt(parts[0]);
		type = (parts.length > 1) ? getType(parts[1]) : 0;
		instance = (parts.length > 2) ? Integer.parseInt(parts[2]) : 0;
		property = (parts.length > 3) ?getProperty(parts[3]) : 85;
	}
	
	public BACnetAddress(int device, int type, int instance, int property) {
		this.device = device;
		this.type = type;
		this.instance = instance;
		this.property = property;
		//this.address = new Address(String.format("%s.%s.%s.%s", device, type, instance, property));
	}
	
	private int getProperty(String prop) {
		// if object is specified by numeric ID, return it
		MutableInteger mi = new MutableInteger();
		if(mi.parseInt(prop, true)) {
			return mi.getValue();
		}
		
		switch(prop) {
		case "ACKEDTRANSITIONS": return 0;
		case "ACKREQUIRED": return 1;
		case "ACTION": return 2;
		case "ACTIONTEXT": return 3;
		case "ACTIVETEXT": return 4;
		case "ACTIVEVTSESSIONS": return 5;
		case "ALARMVALUE": return 6;
		case "ALARMVALUES": return 7;
		case "ALL": return 8;
		case "ALLWRITESSUCCESSFUL": return 9;
		case "APDUSEGMENTTIMEOUT": return 10;
		case "APDUTIMEOUT": return 11;
		case "APPLICATIONSOFTWAREVERSION": return 12;
		case "ARCHIVE": return 13;
		case "BIAS": return 14;
		case "CHANGEOFSTATECOUNT": return 15;
		case "CHANGEOFSTATETIME": return 16;
		case "NOTIFICATIONCLASS": return 17;
		case "CONTROLLEDVARIABLEREFERENCE": return 19;
		case "CONTROLLEDVARIABLEUNITS": return 20;
		case "CONTROLLEDVARIABLEVALUE": return 21;
		case "COVINCREMENT": return 22;
		case "DATELIST": return 23;
		case "DAYLIGHTSAVINGSSTATUS": return 24;
		case "DEADBAND": return 25;
		case "DERIVATIVECONSTANT": return 26;
		case "DERIVATIVECONSTANTUNITS": return 27;
		case "DESCRIPTION": return 28;
		case "DESCRIPTIONOFHALT": return 29;
		case "DEVICEADDRESSBINDING": return 30;
		case "DEVICETYPE": return 31;
		case "EFFECTIVEPERIOD": return 32;
		case "ELAPSEDACTIVETIME": return 33;
		case "ERRORLIMIT": return 34;
		case "EVENTENABLE": return 35;
		case "EVENTSTATE": return 36;
		case "EVENTTYPE": return 37;
		case "EXCEPTIONSCHEDULE": return 38;
		case "FAULTVALUES": return 39;
		case "FEEDBACKVALUE": return 40;
		case "FILEACCESSMETHOD": return 41;
		case "FILESIZE": return 42;
		case "FILETYPE": return 43;
		case "FIRMWAREREVISION": return 44;
		case "HIGHLIMIT": return 45;
		case "INACTIVETEXT": return 46;
		case "INPROCESS": return 47;
		case "INSTANCEOF": return 48;
		case "INTEGRALCONSTANT": return 49;
		case "INTEGRALCONSTANTUNITS": return 50;
		case "LIMITENABLE": return 52;
		case "LISTOFGROUPMEMBERS": return 53;
		case "LISTOFOBJECTPROPERTYREFERENCES": return 54;
		case "LOCALDATE": return 56;
		case "LOCALTIME": return 57;
		case "LOCATION": return 58;
		case "LOWLIMIT": return 59;
		case "MANIPULATEDVARIABLEREFERENCE": return 60;
		case "MAXIMUMOUTPUT": return 61;
		case "MAXAPDULENGTHACCEPTED": return 62;
		case "MAXINFOFRAMES": return 63;
		case "MAXMASTER": return 64;
		case "MAXPRESVALUE": return 65;
		case "MINIMUMOFFTIME": return 66;
		case "MINIMUMONTIME": return 67;
		case "MINIMUMOUTPUT": return 68;
		case "MINPRESVALUE": return 69;
		case "MODELNAME": return 70;
		case "MODIFICATIONDATE": return 71;
		case "NOTIFYTYPE": return 72;
		case "NUMBEROFAPDURETRIES": return 73;
		case "NUMBEROFSTATES": return 74;
		case "OBJECTIDENTIFIER": return 75;
		case "OBJECTLIST": return 76;
		case "OBJECTNAME": return 77;
		case "OBJECTPROPERTYREFERENCE": return 78;
		case "OBJECTTYPE": return 79;
		case "OPTIONAL": return 80;
		case "OUTOFSERVICE": return 81;
		case "OUTPUTUNITS": return 82;
		case "EVENTPARAMETERS": return 83;
		case "POLARITY": return 84;
		case "PRESENTVALUE": return 85;
		case "PRIORITY": return 86;
		case "PRIORITYARRAY": return 87;
		case "PRIORITYFORWRITING": return 88;
		case "PROCESSIDENTIFIER": return 89;
		case "PROGRAMCHANGE": return 90;
		case "PROGRAMLOCATION": return 91;
		case "PROGRAMSTATE": return 92;
		case "PROPORTIONALCONSTANT": return 93;
		case "PROPORTIONALCONSTANTUNITS": return 94;
		case "PROTOCOLOBJECTTYPESSUPPORTED": return 96;
		case "PROTOCOLSERVICESSUPPORTED": return 97;
		case "PROTOCOLVERSION": return 98;
		case "READONLY": return 99;
		case "REASONFORHALT": return 100;
		case "RECIPIENTLIST": return 102;
		case "RELIABILITY": return 103;
		case "RELINQUISHDEFAULT": return 104;
		case "REQUIRED": return 105;
		case "RESOLUTION": return 106;
		case "SEGMENTATIONSUPPORTED": return 107;
		case "SETPOINT": return 108;
		case "SETPOINTREFERENCE": return 109;
		case "STATETEXT": return 110;
		case "STATUSFLAGS": return 111;
		case "SYSTEMSTATUS": return 112;
		case "TIMEDELAY": return 113;
		case "TIMEOFACTIVETIMERESET": return 114;
		case "TIMEOFSTATECOUNTRESET": return 115;
		case "TIMESYNCHRONIZATIONRECIPIENTS": return 116;
		case "UNITS": return 117;
		case "UPDATEINTERVAL": return 118;
		case "UTCOFFSET": return 119;
		case "VENDORIDENTIFIER": return 120;
		case "VENDORNAME": return 121;
		case "VTCLASSESSUPPORTED": return 122;
		case "WEEKLYSCHEDULE": return 123;
		case "ATTEMPTEDSAMPLES": return 124;
		case "AVERAGEVALUE": return 125;
		case "BUFFERSIZE": return 126;
		case "CLIENTCOVINCREMENT": return 127;
		case "COVRESUBSCRIPTIONINTERVAL": return 128;
		case "EVENTTIMESTAMPS": return 130;
		case "LOGBUFFER": return 131;
		case "LOGDEVICEOBJECTPROPERTY": return 132;
		case "ENABLE": return 133;
		case "LOGINTERVAL": return 134;
		case "MAXIMUMVALUE": return 135;
		case "MINIMUMVALUE": return 136;
		case "NOTIFICATIONTHRESHOLD": return 137;
		case "PROTOCOLREVISION": return 139;
		case "RECORDSSINCENOTIFICATION": return 140;
		case "RECORDCOUNT": return 141;
		case "STARTTIME": return 142;
		case "STOPTIME": return 143;
		case "STOPWHENFULL": return 144;
		case "TOTALRECORDCOUNT": return 145;
		case "VALIDSAMPLES": return 146;
		case "WINDOWINTERVAL": return 147;
		case "WINDOWSAMPLES": return 148;
		case "MAXIMUMVALUETIMESTAMP": return 149;
		case "MINIMUMVALUETIMESTAMP": return 150;
		case "VARIANCEVALUE": return 151;
		case "ACTIVECOVSUBSCRIPTIONS": return 152;
		case "BACKUPFAILURETIMEOUT": return 153;
		case "CONFIGURATIONFILES": return 154;
		case "DATABASEREVISION": return 155;
		case "DIRECTREADING": return 156;
		case "LASTRESTORETIME": return 157;
		case "MAINTENANCEREQUIRED": return 158;
		case "MEMBEROF": return 159;
		case "MODE": return 160;
		case "OPERATIONEXPECTED": return 161;
		case "SETTING": return 162;
		case "SILENCED": return 163;
		case "TRACKINGVALUE": return 164;
		case "ZONEMEMBERS": return 165;
		case "LIFESAFETYALARMVALUES": return 166;
		case "MAXSEGMENTSACCEPTED": return 167;
		case "PROFILENAME": return 168;
		case "AUTOSLAVEDISCOVERY": return 169;
		case "MANUALSLAVEADDRESSBINDING": return 170;
		case "SLAVEADDRESSBINDING": return 171;
		case "SLAVEPROXYENABLE": return 172;
		case "LASTNOTIFYRECORD": return 173;
		case "SCHEDULEDEFAULT": return 174;
		case "ACCEPTEDMODES": return 175;
		case "ADJUSTVALUE": return 176;
		case "COUNT": return 177;
		case "COUNTBEFORECHANGE": return 178;
		case "COUNTCHANGETIME": return 179;
		case "COVPERIOD": return 180;
		case "INPUTREFERENCE": return 181;
		case "LIMITMONITORINGINTERVAL": return 182;
		case "LOGGINGOBJECT": return 183;
		case "LOGGINGRECORD": return 184;
		case "PRESCALE": return 185;
		case "PULSERATE": return 186;
		case "SCALE": return 187;
		case "SCALEFACTOR": return 188;
		case "UPDATETIME": return 189;
		case "VALUEBEFORECHANGE": return 190;
		case "VALUESET": return 191;
		case "VALUECHANGETIME": return 192;
		case "ALIGNINTERVALS": return 193;
		case "INTERVALOFFSET": return 195;
		case "LASTRESTARTREASON": return 196;
		case "LOGGINGTYPE": return 197;
		case "RESTARTNOTIFICATIONRECIPIENTS": return 202;
		case "TIMEOFDEVICERESTART": return 203;
		case "TIMESYNCHRONIZATIONINTERVAL": return 204;
		case "TRIGGER": return 205;
		case "UTCTIMESYNCHRONIZATIONRECIPIENTS": return 206;
		case "NODESUBTYPE": return 207;
		case "NODETYPE": return 208;
		case "STRUCTUREDOBJECTLIST": return 209;
		case "SUBORDINATEANNOTATIONS": return 210;
		case "SUBORDINATELIST": return 211;
		case "ACTUALSHEDLEVEL": return 212;
		case "DUTYWINDOW": return 213;
		case "EXPECTEDSHEDLEVEL": return 214;
		case "FULLDUTYBASELINE": return 215;
		case "REQUESTEDSHEDLEVEL": return 218;
		case "SHEDDURATION": return 219;
		case "SHEDLEVELDESCRIPTIONS": return 220;
		case "SHEDLEVELS": return 221;
		case "STATEDESCRIPTION": return 222;
		case "DOORALARMSTATE": return 226;
		case "DOOREXTENDEDPULSETIME": return 227;
		case "DOORMEMBERS": return 228;
		case "DOOROPENTOOLONGTIME": return 229;
		case "DOORPULSETIME": return 230;
		case "DOORSTATUS": return 231;
		case "DOORUNLOCKDELAYTIME": return 232;
		case "LOCKSTATUS": return 233;
		case "MASKEDALARMVALUES": return 234;
		case "SECUREDSTATUS": return 235;
		case "ABSENTEELIMIT": return 244;
		case "ACCESSALARMEVENTS": return 245;
		case "ACCESSDOORS": return 246;
		case "ACCESSEVENT": return 247;
		case "ACCESSEVENTAUTHENTICATIONFACTOR": return 248;
		case "ACCESSEVENTCREDENTIAL": return 249;
		case "ACCESSEVENTTIME": return 250;
		case "ACCESSTRANSACTIONEVENTS": return 251;
		case "ACCOMPANIMENT": return 252;
		case "ACCOMPANIMENTTIME": return 253;
		case "ACTIVATIONTIME": return 254;
		case "ACTIVEAUTHENTICATIONPOLICY": return 255;
		case "ASSIGNEDACCESSRIGHTS": return 256;
		case "AUTHENTICATIONFACTORS": return 257;
		case "AUTHENTICATIONPOLICYLIST": return 258;
		case "AUTHENTICATIONPOLICYNAMES": return 259;
		case "AUTHENTICATIONSTATUS": return 260;
		case "AUTHORIZATIONMODE": return 261;
		case "BELONGSTO": return 262;
		case "CREDENTIALDISABLE": return 263;
		case "CREDENTIALSTATUS": return 264;
		case "CREDENTIALS": return 265;
		case "CREDENTIALSINZONE": return 266;
		case "DAYSREMAINING": return 267;
		case "ENTRYPOINTS": return 268;
		case "EXITPOINTS": return 269;
		case "EXPIRYTIME": return 270;
		case "EXTENDEDTIMEENABLE": return 271;
		case "FAILEDATTEMPTEVENTS": return 272;
		case "FAILEDATTEMPTS": return 273;
		case "FAILEDATTEMPTSTIME": return 274;
		case "LASTACCESSEVENT": return 275;
		case "LASTACCESSPOINT": return 276;
		case "LASTCREDENTIALADDED": return 277;
		case "LASTCREDENTIALADDEDTIME": return 278;
		case "LASTCREDENTIALREMOVED": return 279;
		case "LASTCREDENTIALREMOVEDTIME": return 280;
		case "LASTUSETIME": return 281;
		case "LOCKOUT": return 282;
		case "LOCKOUTRELINQUISHTIME": return 283;
		case "MAXFAILEDATTEMPTS": return 285;
		case "MEMBERS": return 286;
		case "MUSTERPOINT": return 287;
		case "NEGATIVEACCESSRULES": return 288;
		case "NUMBEROFAUTHENTICATIONPOLICIES": return 289;
		case "OCCUPANCYCOUNT": return 290;
		case "OCCUPANCYCOUNTADJUST": return 291;
		case "OCCUPANCYCOUNTENABLE": return 292;
		case "OCCUPANCYLOWERLIMIT": return 294;
		case "OCCUPANCYLOWERLIMITENFORCED": return 295;
		case "OCCUPANCYSTATE": return 296;
		case "OCCUPANCYUPPERLIMIT": return 297;
		case "OCCUPANCYUPPERLIMITENFORCED": return 298;
		case "PASSBACKMODE": return 300;
		case "PASSBACKTIMEOUT": return 301;
		case "POSITIVEACCESSRULES": return 302;
		case "REASONFORDISABLE": return 303;
		case "SUPPORTEDFORMATS": return 304;
		case "SUPPORTEDFORMATCLASSES": return 305;
		case "THREATAUTHORITY": return 306;
		case "THREATLEVEL": return 307;
		case "TRACEFLAG": return 308;
		case "TRANSACTIONNOTIFICATIONCLASS": return 309;
		case "USEREXTERNALIDENTIFIER": return 310;
		case "USERINFORMATIONREFERENCE": return 311;
		case "USERNAME": return 317;
		case "USERTYPE": return 318;
		case "USESREMAINING": return 319;
		case "ZONEFROM": return 320;
		case "ZONETO": return 321;
		case "ACCESSEVENTTAG": return 322;
		case "GLOBALIDENTIFIER": return 323;
		case "VERIFICATIONTIME": return 326;
		case "BASEDEVICESECURITYPOLICY": return 327;
		case "DISTRIBUTIONKEYREVISION": return 328;
		case "DONOTHIDE": return 329;
		case "KEYSETS": return 330;
		case "LASTKEYSERVER": return 331;
		case "NETWORKACCESSSECURITYPOLICIES": return 332;
		case "PACKETREORDERTIME": return 333;
		case "SECURITYPDUTIMEOUT": return 334;
		case "SECURITYTIMEWINDOW": return 335;
		case "SUPPORTEDSECURITYALGORITHMS": return 336;
		case "UPDATEKEYSETTIMEOUT": return 337;
		case "BACKUPANDRESTORESTATE": return 338;
		case "BACKUPPREPARATIONTIME": return 339;
		case "RESTORECOMPLETIONTIME": return 340;
		case "RESTOREPREPARATIONTIME": return 341;
		case "BITMASK": return 342;
		case "BITTEXT": return 343;
		case "ISUTC": return 344;
		case "GROUPMEMBERS": return 345;
		case "GROUPMEMBERNAMES": return 346;
		case "MEMBERSTATUSFLAGS": return 347;
		case "REQUESTEDUPDATEINTERVAL": return 348;
		case "COVUPERIOD": return 349;
		case "COVURECIPIENTS": return 350;
		case "EVENTMESSAGETEXTS": return 351;
		case "EVENTMESSAGETEXTSCONFIG": return 352;
		case "EVENTDETECTIONENABLE": return 353;
		case "EVENTALGORITHMINHIBIT": return 354;
		case "EVENTALGORITHMINHIBITREF": return 355;
		case "TIMEDELAYNORMAL": return 356;
		case "RELIABILITYEVALUATIONINHIBIT": return 357;
		case "FAULTPARAMETERS": return 358;
		case "FAULTTYPE": return 359;
		case "LOCALFORWARDINGONLY": return 360;
		case "PROCESSIDENTIFIERFILTER": return 361;
		case "SUBSCRIBEDRECIPIENTS": return 362;
		case "PORTFILTER": return 363;
		case "AUTHORIZATIONEXEMPTIONS": return 364;
		case "ALLOWGROUPDELAYINHIBIT": return 365;
		case "CHANNELNUMBER": return 366;
		case "CONTROLGROUPS": return 367;
		case "EXECUTIONDELAY": return 368;
		case "LASTPRIORITY": return 369;
		case "WRITESTATUS": return 370;
		case "PROPERTYLIST": return 371;
		case "SERIALNUMBER": return 372;
		case "BLINKWARNENABLE": return 373;
		case "DEFAULTFADETIME": return 374;
		case "DEFAULTRAMPRATE": return 375;
		case "DEFAULTSTEPINCREMENT": return 376;
		case "EGRESSTIME": return 377;
		case "INPROGRESS": return 378;
		case "INSTANTANEOUSPOWER": return 379;
		case "LIGHTINGCOMMAND": return 380;
		case "LIGHTINGCOMMANDDEFAULTPRIORITY": return 381;
		case "MAXACTUALVALUE": return 382;
		case "MINACTUALVALUE": return 383;
		case "POWER": return 384;
		case "TRANSITION": return 385;
		case "EGRESSACTIVE": return 386;
		}
		
		return 85;
	}

	private int getType(String type) {
		// if object is specified by numeric ID, return it
		MutableInteger mi = new MutableInteger();
		if(mi.parseInt(type, true)) {
			return mi.getValue();
		}
		
		int num = 0;
		
		// the string is not valid positive integer - we have to parse text
		
		// normalize string
		type = type.toUpperCase();
		
		// seems it is no abbreviation - replace whitespace
		if(type.length() > 3) {
			type = type.replaceAll("[-_ ]", "");
		}
		
		// abbreviations are used by Delta Controls software
		switch(type) {
		case "AI":
		case "ANALOGINPUT":
			num = 0;
		break;
		case "AO":
		case "ANALOGOUTPUT":
			num = 1;
		break;
		case "AV":
		case "ANALOGVALUE":
			num = 2;
		break;
		case "BI":
		case "BINARYINPUT":
			num = 3;
		break;
		case "BO":
		case "BINARYOUTPUT":
			num = 4;
		break;
		case "BV":
		case "BINARYVALUE":
			num = 5;
		break;
		case "CAL":
		case "CALENDAR":
			num = 6;
		break;
		case "DEV":
		case "DEVICE":
			num = 8;
		break;
		case "EV":
		case "EVENTENROLLMENT":
			num = 9;
		break;
		case "CO":
		case "LOOP":
			num = 12;
		break;
		case "MI":
		case "MULTISTATEINPUT":
			num = 13;
		break;
		case "MO":
		case "MULTISTATEOUTPUT":
			num = 14;
		break;
		case "EVC":
		case "NOTIFICATIONCLASS":
			num = 15;
		break;
		case "PG":
		case "PROGRAM":
			num = 16;
		break;
		case "SCH":
		case "SCHEDULE":
			num = 17;
		break;
		case "MV":
		case "MULTISTATEVALUE":
			num = 19;
		break;
		case "TL":
		case "TRENDLOG":
			num = 20;
		break;
		case "EVL":
		case "EVENTLOG":
			num = 25;
		break;
		case "MT":
		case "TRENDLOGMULTIPLE":
			num = 27;
		break;
		default:
		break;
		}
		return num;
	}

	public int getInstance() {
		return this.instance;
	}

	public int getProperty() {
		return this.property;
	}
	
	public int getType() {
		return this.type;
	}
	
	public int getDevice() {
		return this.device;
	}

	@Override
	public String toString() {
		return "BACnetAddress [device=" + device + ", type="
				+ type + ", instance=" + instance + ", property=" + property + "]";
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + device;
		result = prime * result + instance;
		result = prime * result + property;
		result = prime * result + type;
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		BACnetAddress other = (BACnetAddress) obj;
		if (device != other.device)
			return false;
		if (instance != other.instance)
			return false;
		if (property != other.property)
			return false;
		if (type != other.type)
			return false;
		return true;
	}
	
	

}
