qsoID = $data['COL_PRIMARY_KEY'];
		$CI =& get_instance();
		// Get Date format
		if($CI->session->userdata('user_date_format')) {
			// If Logged in and session exists
			$custom_date_format = $CI->session->userdata('user_date_format');
		} else {
			// Get Default date format from /config/cloudlog.php
			$custom_date_format = $CI->config->item('qso_date_format');
		}
		$this->qsoDateTime = date($custom_date_format . " H:i", strtotime($data['COL_TIME_ON']));
		$this->de = $data['COL_STATION_CALLSIGN'];
		$this->dx = $data['COL_CALL'];
		$this->mode = $data['COL_MODE'] ?? '';
		$this->submode = $data['COL_SUBMODE'] ?? '';
		$this->band = $data['COL_BAND'];
		$this->bandRX = $data['COL_BAND_RX'] ?? '';
		$this->rstR = $data['COL_RST_RCVD'];
		$this->rstS = $data['COL_RST_SENT'];
		$this->propagationMode = $data['COL_PROP_MODE'] ?? '';
		$this->satelliteMode = $data['COL_SAT_MODE'] != '' ? (strlen($data['COL_SAT_MODE']) == 2 ? (strtoupper($data['COL_SAT_MODE'][0]).'/'.strtoupper($data['COL_SAT_MODE'][1])) : strtoupper($data['COL_SAT_MODE'])) : '';
		$this->satelliteName = $data['COL_SAT_NAME'] ?? '';
		$this->name = $data['COL_NAME'] ?? '';
		$this->email = $data['COL_EMAIL'] ?? '';
		$this->address = $data['COL_ADDRESS'] ?? '';
		$this->deGridsquare = $data['COL_MY_GRIDSQUARE'] ?? '';
		$this->deIOTA = $data['COL_MY_IOTA'] ?? '';
		$this->deSig = $data['COL_MY_SIG'] ?? '';
		$this->deSigInfo = $data['COL_MY_SIG_INFO'] ?? '';
		$this->deIOTAIslandID = $data['COL_MY_IOTA_ISLAND_ID'] ?? '';
		$this->deSOTAReference = $data['COL_MY_SOTA_REF'] ?? '';
		$this->deVUCCGridsquares = $data['COL_MY_VUCC_GRIDS'] ?? '';
		$this->stationGridsquare = $data['station_gridsquare'] ?? '';
		$this->dxGridsquare = $data['COL_GRIDSQUARE'] ?? '';
		$this->dxIOTA = $data['COL_IOTA'] ?? '';
		$this->dxSig = $data['COL_SIG'] ?? '';
		$this->dxSigInfo = $data['COL_SIG_INFO'] ?? '';
		$this->dxDARCDOK = $data['COL_DARC_DOK'] ?? '';
		$this->dxSOTAReference = $data['COL_SOTA_REF'] ?? '';
		$this->dxPOTAReference = $data['COL_POTA_REF'] ?? '';
		$this->dxWWFFReference = $data['COL_WWFF_REF'] ?? '';
		$this->dxVUCCGridsquares = $data['COL_VUCC_GRIDS'] ?? '';
		$this->QSLMsg = $data['COL_QSLMSG'] ?? '';
		$this->QSLReceivedDate = ($data['COL_QSLRDATE'] === null) ? null : DateTime::createFromFormat("Y-m-d H:i:s", $data['COL_QSLRDATE'], new DateTimeZone('UTC'));
		$this->QSLReceived = ($data['COL_QSL_RCVD'] === null) ? '' : $data['COL_QSL_RCVD'];
		$this->QSLReceivedVia = ($data['COL_QSL_RCVD_VIA'] === null) ? '' : $data['COL_QSL_RCVD_VIA'];
		$this->QSLSentDate = ($data['COL_QSLSDATE'] === null) ? null : DateTime::createFromFormat("Y-m-d H:i:s", $data['COL_QSLSDATE'], new DateTimeZone('UTC'));
		$this->QSLSent = ($data['COL_QSL_SENT'] === null) ? '' : $data['COL_QSL_SENT'];
		$this->QSLSentVia = ($data['COL_QSL_SENT_VIA'] === null) ? '' : $data['COL_QSL_SENT_VIA'];
		$this->QSLVia = ($data['COL_QSL_VIA'] === null) ? '' : $data['COL_QSL_VIA'];
		$this->qsl = $this->getQslString($data, $custom_date_format);
		$this->lotw = $this->getLotwString($data, $custom_date_format);
		$this->eqsl = $this->getEqslString($data, $custom_date_format);
		$this->cqzone = ($data['COL_CQZ'] === null) ? '' : ''.$data['COL_CQZ'].'';
		$this->state = ($data['COL_STATE'] === null) ? '' :$data['COL_STATE'];
		$this->dxcc = (($data['name'] ?? null) === null) ? '- NONE -' : ''.ucwords(strtolower($data['name']), "- (/").'';
		$this->iota = ($data['COL_IOTA'] === null) ? '' : $this->getIotaLink($data['COL_IOTA']);
		if (array_key_exists('end', $data)) {
			$this->end = ($data['end'] === null) ? null : DateTime::createFromFormat("Y-m-d", $data['end'], new DateTimeZone('UTC'));
		} else {
			$this->end = null;
		}
		$this->callsign = ($data['callsign'] ?? null === null) ? '' :$data['callsign'];
		$this->lastupload = ($data['lastupload'] ?? null === null) ? '' : date($custom_date_format . " H:i", strtotime($data['lastupload'] ?? null));
		$this->lotw_hint = $this->getLotwHint($data['lastupload'] ?? null);
	}
	/**
	 * @return string
	 */
	function getLotwHint($lastupload): string
	{
		$lotw_hint = '';
		if ($lastupload !== null) {
			$diff = time();
			$diff = (time() - strtotime($lastupload)) / 86400;
			if ($diff > 365) {
				$lotw_hint = ' lotw_info_red';
			} elseif ($diff > 30) {
				$lotw_hint = ' lotw_info_orange';
			} elseif ($diff > 7) {
				$lotw_hint = ' lotw_info_yellow';
			}
		}
		return $lotw_hint;
	}
	/**
	 * @return string
	 */
	function getQSLString($data, $custom_date_format): string
	{
		$CI =& get_instance();
		$qslstring = 'lang->line('general_word_sent');
				break;
			case "Q":
				$qslstring .= "class=\"qsl-yellow\" data-toggle=\"tooltip\" data-original-title=\"".$CI->lang->line('general_word_queued');
				break;
			case "R":
				$qslstring .= "class=\"qsl-yellow\" data-toggle=\"tooltip\" data-original-title=\"".$CI->lang->line('general_word_requested');
				break;
			case "I":
				$qslstring .= "class=\"qsl-grey\" data-toggle=\"tooltip\" data-original-title=\"".$CI->lang->line('general_word_invalid_ignore');
				break;
			default:
			$qslstring .= "class=\"qsl-red";
				break;
			}
			if ($data['COL_QSLSDATE'] != null) {
				$timestamp = strtotime($data['COL_QSLSDATE']);
				$qslstring .= " "  .($timestamp != '' ? date($custom_date_format, $timestamp) : '');
			}
		} else {
			$qslstring .= "class=\"qsl-red";
		}
		if ($data['COL_QSL_SENT_VIA'] != "") {
			switch ($data['COL_QSL_SENT_VIA']) {
				case "B":
					$qslstring .= " (" . $CI->lang->line('general_word_qslcard_bureau') . ")";
					break;
				case "D":
				$qslstring .= " (".$CI->lang->line('general_word_qslcard_direct').")";
					break;
				case "M":
				$qslstring .= " (".$CI->lang->line('general_word_qslcard_via').": ".($data['COL_QSL_VIA'] !="" ? $data['COL_QSL_VIA']:"n/a").")";
					break;
				case "E":
				$qslstring .= " (".$CI->lang->line('general_word_qslcard_electronic').")";
					break;
			}
		}
			$qslstring .= '">▲lang->line('general_word_received');
					break;
					case "Q":
						$qslstring .= "class=\"qsl-yellow\" data-toggle=\"tooltip\" data-original-title=\"".$CI->lang->line('general_word_queued');
					break;
					case "R":
						$qslstring .= "class=\"qsl-yellow\" data-toggle=\"tooltip\" data-original-title=\"".$CI->lang->line('general_word_requested');
					break;
					case "I":
						$qslstring .= "class=\"qsl-grey\" data-toggle=\"tooltip\" data-original-title=\"".$CI->lang->line('general_word_invalid_ignore');
					break;
					default:
					$qslstring .= "class=\"qsl-red";
					break;
				}
				if ($data['COL_QSLRDATE'] != null) {
					$timestamp = strtotime($data['COL_QSLRDATE']);
					$qslstring .= " "  .($timestamp != '' ? date($custom_date_format, $timestamp) : '');
				}
			} else {
			$qslstring .= "class=\"qsl-red"; }
			if ($data['COL_QSL_RCVD_VIA'] != "") {
				switch ($data['COL_QSL_RCVD_VIA']) {
					case "B":
					$qslstring .= " (".$CI->lang->line('general_word_qslcard_bureau').")";
						break;
					case "D":
					$qslstring .= " (".$CI->lang->line('general_word_qslcard_direct').")";
						break;
					case "M":
					$qslstring .= " (Manager)";
						break;
					case "E":
					$qslstring .= " (".$CI->lang->line('general_word_qslcard_electronic').")";
						break;
				}
			}
			$qslstring .= '">▼';
			if ($data['qslcount'] ?? null != null) {
				$qslstring .= ' ';
			}
		return $qslstring;
	}
	/**
	 * @return string
	 */
	function getLotwString($data, $custom_date_format): string
	{
		$CI =& get_instance();
		$lotwstring = 'lang->line('lotw_short')." ".$CI->lang->line('general_word_sent');
			if ($data['COL_LOTW_QSLSDATE'] != null) {
				$timestamp = strtotime($data['COL_LOTW_QSLSDATE']);
				$lotwstring .= " ". ($timestamp != '' ? date($custom_date_format, $timestamp) : '');
			}
			$lotwstring .= "\" data-toggle=\"tooltip\"";
		}
		$lotwstring .= ' class="lotw-' . (($data['COL_LOTW_QSL_SENT']=='Y') ? 'green' : 'red') . '">▲';
		$lotwstring .= 'lang->line('lotw_short') ." ". $CI->lang->line('general_word_received');
			if ($data['COL_LOTW_QSLRDATE'] != null) {
				$timestamp = strtotime($data['COL_LOTW_QSLRDATE']);
				$lotwstring .=  " ". ($timestamp != '' ? date($custom_date_format, $timestamp) : '');
			}
			$lotwstring .= "\" data-toggle=\"tooltip\"";
		}
		$lotwstring .= ' class="lotw-' . (($data['COL_LOTW_QSL_RCVD']=='Y') ? 'green':'red') . '">▼';
		return $lotwstring;
	}
	/**
	 * @return string
	 */
	function getEqslString($data, $custom_date_format): string
	{
		$CI =& get_instance();
		$eqslstring = 'lang->line('eqsl_short')." ".$CI->lang->line('general_word_sent');
			if ($data['COL_EQSL_QSLSDATE'] != null) {
				$timestamp = strtotime($data['COL_EQSL_QSLSDATE']);
				$eqslstring .=  " ".($timestamp!=''?date($custom_date_format, $timestamp):'');
			}
			$eqslstring .= "\" data-toggle=\"tooltip\"";
		}
		$eqslstring .= ' class="eqsl-' . (($data['COL_EQSL_QSL_SENT'] =='Y') ? 'green':'red') . '">▲lang->line('eqsl_short')." ".$CI->lang->line('general_word_received');
			if ($data['COL_EQSL_QSLRDATE'] != null) {
				$timestamp = strtotime($data['COL_EQSL_QSLRDATE']);
				$eqslstring .= " ".($timestamp!=''?date($custom_date_format, $timestamp):'');
			}
			$eqslstring .= "\" data-toggle=\"tooltip\"";
		}
		$eqslstring .= ' class="eqsl-' . (($data['COL_EQSL_QSL_RCVD'] =='Y')?'green':'red') . '">';
		if($data['COL_EQSL_QSL_RCVD'] =='Y') {
			$eqslstring .= '▼';
		} else {
			$eqslstring .= '▼';
		}
		$eqslstring .= '';
		return $eqslstring;
	}
	/**
	 * @return string
	 */
	public function getQsoID(): string
	{
		return $this->qsoID;
	}
	/**
	 * @return DateTime
	 */
	public function getQsoDateTime(): string
	{
		return $this->qsoDateTime;
	}
	/**
	 * @return string
	 */
	public function getDe(): string
	{
		return $this->de;
	}
	/**
	 * @return string
	 */
	public function getDx(): string
	{
		return $this->dx;
	}
	/**
	 * @return string
	 */
	public function getMode(): string
	{
		return $this->mode;
	}
	/**
	 * @return string
	 */
	public function getSubmode(): string
	{
		return $this->submode;
	}
	/**
	 * @return string
	 */
	public function getBand(): string
	{
		return $this->band;
	}
	/**
	 * @return string
	 */
	public function getBandRX(): string
	{
		return $this->bandRX;
	}
	/**
	 * @return string
	 */
	public function getRstR(): string
	{
		return $this->rstR;
	}
	/**
	 * @return string
	 */
	public function getRstS(): string
	{
		return $this->rstS;
	}
	/**
	 * @return string
	 */
	public function getPropagationMode(): string
	{
		return $this->propagationMode;
	}
	/**
	 * @return string
	 */
	public function getSatelliteMode(): string
	{
		return $this->satelliteMode;
	}
	/**
	 * @return string
	 */
	public function getSatelliteName(): string
	{
		return $this->satelliteName;
	}
	/**
	 * @return string
	 */
	public function getName(): string
	{
		return $this->name;
	}
	/**
	 * @return string
	 */
	public function getEmail(): string
	{
		return $this->email;
	}
	/**
	 * @return string
	 */
	public function getAddress(): string
	{
		return $this->address;
	}
	/**
	 * @return string
	 */
	public function getDeGridsquare(): string
	{
		return $this->deGridsquare;
	}
	/**
	 * @return string
	 */
	public function getDeIOTA(): string
	{
		return $this->deIOTA;
	}
	/**
	 * @return string
	 */
	public function getDeSig(): string
	{
		return $this->deSig;
	}
	/**
	 * @return string
	 */
	public function getDeSigInfo(): string
	{
		return $this->deSigInfo;
	}
	/**
	 * @return string
	 */
	public function getDeIOTAIslandID(): string
	{
		return $this->deIOTAIslandID;
	}
	/**
	 * @return string
	 */
	public function getDeSOTAReference(): string
	{
		return $this->deSOTAReference;
	}
	/**
	 * @return string[]
	 */
	public function getDeVUCCGridsquares(): string
	{
		return $this->deVUCCGridsquares;
	}
	/**
	 * @return string
	 */
	public function getDxGridsquare(): string
	{
		return $this->dxGridsquare;
	}
	/**
	 * @return string
	 */
	public function getDxIOTA(): string
	{
		return $this->dxIOTA;
	}
	/**
	 * @return string
	 */
	public function getDxSig(): string
	{
		return $this->dxSig;
	}
	/**
	 * @return string
	 */
	public function getDxSigInfo(): string
	{
		return $this->dxSigInfo;
	}
	/**
	 * @return string
	 */
	public function getDxDARCDOK(): string
	{
		return $this->dxDARCDOK;
	}
	/**
	 * @return string
	 */
	public function getDxSOTAReference(): string
	{
		return $this->dxSOTAReference;
	}
	/**
	 * @return string
	 */
	public function getDxPOTAReference(): string
	{
		return $this->dxPOTAReference;
	}
	/**
	 * @return string
	 */
	public function getWWFFReference(): string
	{
		return $this->dxWWFFReference;
	}
	/**
	 * @return string[]
	 */
	public function getDxVUCCGridsquares(): string
	{
		return $this->dxVUCCGridsquares;
	}
	/**
	 * @return string
	 */
	public function getQSLMsg(): string
	{
		return $this->QSLMsg;
	}
	/**
	 * @return ?DateTime
	 */
	public function getQSLReceivedDate(): ?DateTime
	{
		return $this->QSLReceivedDate;
	}
	/**
	 * @return string
	 */
	public function getQSLReceived(): string
	{
		return $this->QSLReceived;
	}
	/**
	 * @return string
	 */
	public function getQSLReceivedVia(): string
	{
		return $this->QSLReceivedVia;
	}
	/**
	 * @return ?DateTime
	 */
	public function getQSLSentDate(): ?DateTime
	{
		return $this->QSLSentDate;
	}
	/**
	 * @return string
	 */
	public function getQSLSent(): string
	{
		return $this->QSLSent;
	}
	/**
	 * @return string
	 */
	public function getQSLSentVia(): string
	{
		return $this->QSLSentVia;
	}
	/**
	 * @return string
	 */
	public function getqsl(): string
	{
		return $this->qsl;
	}
	/**
	 * @return string
	 */
	public function getlotw(): string
	{
		return $this->lotw;
	}
	/**
	 * @return string
	 */
	public function geteqsl(): string
	{
		return $this->eqsl;
	}
	/**
	 * @return string
	 */
	public function getQSLVia(): string
	{
		return $this->QSLVia;
	}
	public function getDXCC(): string
	{
		return $this->dxcc;
	}
	public function getCqzone(): string
	{
		return $this->cqzone;
	}
	public function getState(): string
	{
		return $this->state;
	}
	public function getIOTA(): string
	{
		return $this->iota;
	}
	public function toArray(): array
	{
		return [
			'qsoID' => $this->qsoID,
			'qsoDateTime' => $this->qsoDateTime,
			'de' => $this->de,
			'dx' => $this->dx,
			'mode' => $this->getFormattedMode(),
			'rstS' => $this->rstS,
			'rstR' => $this->rstR,
			'band' => $this->getFormattedBand(),
			'deRefs' => $this->getFormattedDeRefs(),
			'dxRefs' => $this->getFormattedDxRefs(),
			'qslVia' => $this->QSLVia,
			'qsl' => $this->getqsl(),
			'lotw' => $this->getlotw(),
			'eqsl' => $this->geteqsl(),
			'qslMessage' => $this->getQSLMsg(),
			'name' => $this->getName(),
			'dxcc' => $this->getDXCC(),
			'state' => $this->getState(),
			'cqzone' => $this->getCqzone(),
			'iota' => $this->getIOTA(),
			'end' => $this->end === null ? null : $this->end->format("Y-m-d"),
			'callsign' => $this->callsign,
			'lastupload' => $this->lastupload,
			'lotw_hint' => $this->lotw_hint,
		];
	}
	private function getFormattedMode(): string
	{
		if ($this->submode !== '') {
			return $this->submode;
		} else {
			return $this->mode;
		}
	}
	private function getFormattedBand(): string
	{
		$label = "";
		if ($this->propagationMode !== '') {
			$label .= $this->propagationMode;
			if ($this->satelliteName !== '') {
				$label .= " " . $this->satelliteName;
				if ($this->satelliteMode !== '') {
					$label .= " " . $this->satelliteMode;
				}
			}
		}
		$label .= " " . $this->band;
		if ($this->bandRX !== '' && $this->band !== '') {
			$label .= "/" . $this->bandRX;
		}
		return trim($label);
	}
	private function getFormattedDeRefs(): string
	{
		$refs = [];
		if ($this->deVUCCGridsquares !== '') {
			$refs[] = $this->deVUCCGridsquares;
		} else {
			if ($this->deGridsquare !== '') {
				$refs[] = $this->deGridsquare;
			}
		}
		if ($this->deIOTA !== '') {
			if ($this->deIOTAIslandID !== '') {
				$refs[] = "IOTA:" . $this->deIOTA . "(" . $this->deIOTAIslandID . ")";
			} else {
				$refs[] = "IOTA:" . $this->deIOTA;
			}
		}
		if ($this->deSOTAReference !== '') {
			$refs[] = "SOTA:" . $this->deSOTAReference;
		}
		if ($this->deSig !== '') {
			$refs[] = $this->deSig . ":" . $this->deSigInfo;
		}
		return trim(implode(" ", $refs));
	}
	private function getFormattedDxRefs(): string
	{
		$refs = [];
		if ($this->dxVUCCGridsquares !== '') {
			$refs[] = '' . $this->dxVUCCGridsquares . ' ' .$this->getQrbLink($this->stationGridsquare, $this->dxVUCCGridsquares, $this->dxGridsquare);
		} else if ($this->dxGridsquare !== '') {
			$refs[] = '' . $this->dxGridsquare . ' ' .$this->getQrbLink($this->stationGridsquare, $this->dxVUCCGridsquares, $this->dxGridsquare);
		}
		if ($this->dxSOTAReference !== '') {
			$refs[] = "SOTA: " . '' . $this->dxSOTAReference. '';
		}
		if ($this->dxPOTAReference !== '') {
			$refs[] = "POTA: " . '' . $this->dxPOTAReference. '';
		}
		if ($this->dxWWFFReference !== '') {
			$refs[] = "WWFF: " . '' . $this->dxWWFFReference. '';
		}
		if ($this->dxSig !== '') {
			$refs[] = $this->dxSig . ":" . $this->dxSigInfo;
		}
		if ($this->dxDARCDOK !== '') {
			$refs[] = "DOK:" . $this->dxDARCDOK;
		}
		return implode(" ", $refs);
	}
	private function getFormattedQSLSent(): string
	{
		$showVia = false;
		$label = [];
		if ($this->QSLSent === "Y") {
			if ($this->QSLSentDate !== null) {
				$label[] = $this->QSLSentDate->format("Y-m-d");
			} else {
				$label[] = "Yes";
			}
			$showVia = true;
		} else if ($this->QSLSent === "N") {
			$label[] = "No";
		} else if ($this->QSLSent === "Q") {
			$label[] = "Queued";
			if ($this->QSLSentDate !== null) {
				$label[] = $this->QSLSentDate->format("Y-m-d");
			}
			$showVia = true;
		} else if ($this->QSLSent === "R") {
			$label[] = "Requested";
			if ($this->QSLSentDate !== null) {
				$label[] = $this->QSLSentDate->format("Y-m-d");
			}
			$showVia = true;
		}
		if ($showVia && $this->QSLSentVia !== '') {
			switch ($this->QSLSentVia) {
				case 'B':
					$label[] = "Bureau";
					break;
				case 'D':
					$label[] = "Direct";
					break;
				case 'E':
					$label[] = "Electronic";
					break;
				case 'M':
					$label[] = "Manager";
					break;
			}
		}
		return trim(implode(" ", $label));
	}
	private function getFormattedQSLReceived(): string
	{
		$showVia = false;
		$label = [];
		if ($this->QSLReceived === "Y") {
			if ($this->QSLReceivedDate !== null) {
				$label[] = $this->QSLReceivedDate->format("Y-m-d");
			} else {
				$label[] = "Yes";
			}
			$showVia = true;
		} else if ($this->QSLReceived === "N") {
			$label[] = "No";
		} else if ($this->QSLReceived === "Q") {
			$label[] = "Queued";
			if ($this->QSLReceivedDate !== null) {
				$label[] = $this->QSLReceivedDate->format("Y-m-d");
			}
			$showVia = true;
		} else if ($this->QSLReceived === "R") {
			$label[] = "Requested";
			if ($this->QSLReceivedDate !== null) {
				$label[] = $this->QSLReceivedDate->format("Y-m-d");
			}
			$showVia = true;
		}
		if ($showVia && $this->QSLReceivedVia !== '') {
			switch ($this->QSLReceivedVia) {
				case 'B':
					$label[] = "Bureau";
					break;
				case 'D':
					$label[] = "Direct";
					break;
				case 'E':
					$label[] = "Electronic";
					break;
				case 'M':
					$label[] = "Manager";
					break;
			}
		}
		return trim(implode(" ", $label));
	}
	private function getQrbLink($mygrid, $grid, $vucc) : string
	{
		if (!empty($grid)) {
			return '';
		} else if (!empty($vucc)) {
			return '';
		}
		return '';
	}
	private function getIotaLink($iota) : string
	{
		if ($iota !== '') {
			return ''.$iota.' ';
		}
		return '';
	}
}