import { format as dateFormat, parseISO as dateParseISO } from 'date-fns';

/**
 * Utils service
 */
export class UtilsService {
	/**
	 * Instance  of utils service
	 */
	private static _instance: UtilsService | null = null;

	/**
	 * Public path of utils service
	 */
	private publicPath: string;

	/**
	 * Creates an instance of utils service.
	 */
	constructor() {
		this.publicPath = process.env.BASE_URL;
	}

	/**
	 * Gets instance
	 * @returns instance
	 */
	public static getInstance(): UtilsService {
		if (this._instance === null) {
			this._instance = new UtilsService();
		}
		return this._instance;
	}

	/**
	 * Gets nl2 br
	 * @param [text]
	 * @returns nl2 br
	 */
	public getNl2Br(text?: string): string {
		if (text !== null && text !== undefined && text !== '') {
			return text.trim().replaceAll('\n', '<br/>');
		}
		return text;
	}

	/**
	 * Gets date
	 * @param [date]
	 * @param [format]
	 * @returns
	 */
	public getDate(date?: string | Date, format?: string) {
		if (date === null || date === undefined || date === '') {
			date = new Date();
		}
		if (format === null || format === undefined) {
			format = "yyyy-MM-dd'T'HH:mm:ss";
		}
		if (date instanceof Date) {
			return dateFormat(date, format);
		} else {
			return dateFormat(dateParseISO(date), format);
		}
	}

	/**
	 * Determines whether null is
	 *
	 * @param input
	 * @returns true if null
	 */
	public isNull(input: any): boolean {
		if (typeof input === 'undefined' || input === null) {
			return true;
		}
		if (typeof input === 'string') {
			if (input.split(' ').join('') === '') {
				return true;
			}
		}
		if (typeof input === 'number') {
			if (input === 0) {
				return true;
			}
		}
		if (Array.isArray(input)) {
			if (input.length === 0) {
				return true;
			}
		}
		return false;
	}

	/**
	 * Determines whether not null is
	 *
	 * @param input
	 * @returns true if not null
	 */
	public isNotNull(input: any): boolean {
		return !this.isNull(input);
	}

	/**
	 * Gets donghsno
	 *
	 * @param [dong]
	 * @param [hsno]
	 * @returns
	 */
	public getJobTypeNm(lJobType?: string, mJobType?: string, sJobType?: string) {
		const jonTypes: string[] = [];
		if (this.isNull(sJobType) && this.isNotNull(lJobType)) {
			jonTypes.push(lJobType);
		}
		if (this.isNotNull(mJobType)) {
			jonTypes.push(mJobType);
		}
		if (this.isNotNull(sJobType)) {
			jonTypes.push(sJobType);
		}
		return jonTypes.join(' > ');
	}

	/**
	 * Gets text2 html
	 * @param [text]
	 * @returns
	 */
	public getText2Html(text?: string) {
		if (text !== undefined && text !== null && text !== '') {
			return text.replaceAll('  ', '&nbsp; ').replaceAll('\n', '<br/>');
		} else {
			return '';
		}
	}

	/**
	 * Gets work wki send
	 *
	 * @param [workWkiPushYn]
	 * @param [workWkiSmsYn]
	 * @returns
	 */
	public getWorkWkiSend(workWkiPushYn?: string, workWkiSmsYn?: string) {
		if (workWkiPushYn === 'Y' || workWkiSmsYn === 'Y') {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * Gets donghsno
	 *
	 * @param [dong]
	 * @param [hsno]
	 * @returns
	 */
	public getDonghsno(dong?: string, hsno?: string) {
		if (this.isNull(dong) || this.isNull(hsno)) {
			return '111';
		}
		if (/^[0-9]+$/.test(dong) && /^[0-9]+$/.test(hsno)) {
			return dong + '동 ' + hsno + '호';
		} else if (/^[0-9]+$/.test(dong)) {
			return dong + '동 ' + hsno;
		} else if (/^[0-9]+$/.test(hsno)) {
			return dong + ' ' + hsno + '호';
		}
		return dong + ' ' + hsno;
	}

	/**
	 * Today  of utils service
	 */
	private _today: Date = null;

	/**
	 * Gets date
	 * @param [date]
	 * @param [format]
	 * @returns
	 */
	public getDatePass(date?: string | Date) {
		if (date === null || date === undefined || date === '') {
			return '';
		}
		let fromDate: Date = null;
		if (date instanceof Date) {
			fromDate = date;
		} else {
			fromDate = dateParseISO(this.showDate(date, '2020-12-31'));
		}
		if (this._today === null) {
			this._today = new Date();
		}
		if (this._today.getTime() > fromDate.getTime()) {
			return '(' + Math.floor((this._today.getTime() - fromDate.getTime()) / 1000 / 60 / 60 / 24) + '일 경과)';
		} else {
			return '';
		}
	}

	/**
	 * Gets date object
	 *
	 * @param [date]
	 * @returns date of date object
	 */
	public getDateObject(date?: string | Date): Date {
		if (date === null || date === undefined || date === '') {
			date = new Date();
		}
		if (date instanceof Date) {
			return date;
		} else {
			return dateParseISO(date);
		}
	}

	/**
	 * Gets date add day
	 *
	 * @param [date]
	 * @param [addDay]
	 * @param [format]
	 * @returns
	 */
	public getDateAddDay(date?: string | Date, addDay?: number, format?: string) {
		if (date === null || date === undefined || date === '') {
			date = new Date();
		}
		const baseDate: Date = date instanceof Date ? date : dateParseISO(date);
		baseDate.setDate(baseDate.getDate() + addDay);
		return this.getDate(dateFormat(baseDate, 'yyyy-MM-dd HH:mm:ss'), format);
	}

	/**
	 * Parses tel
	 *
	 * @param tel
	 * @returns
	 */
	public parseTel(tel: string) {
		if (tel !== null && tel !== undefined) {
			return tel.replace(/((\\+|)[0-9][0-9\\-]{10,20}[0-9])/g, '<a href="tel:$1">$1</a>');
		} else {
			return '-';
		}
	}

	/**
	 * Shows date
	 *
	 * @param date
	 * @returns
	 */
	public showDate(date: string, def = '___-__-__') {
		if (date !== null && date !== '' && date !== undefined) {
			if (date.includes('T')) {
				return date.split('T')[0];
			} else if (date.length === 8) {
				return date.substring(0, 4) + '-' + date.substring(4, 6) + '-' + date.substring(6, 8);
			} else {
				return date;
			}
		}
		return def;
	}

	/**
	 * Shows date range
	 *
	 * @param from
	 * @param to
	 * @returns
	 */
	public showDateRange(from: string, to: string) {
		return this.showDate(from, '') + '~' + this.showDate(to, '');
	}

	/**
	 * Shows text join
	 *
	 * @param [delimiter]
	 * @param data
	 * @returns
	 */
	public showTextJoin(delimiter = ' - ', ...data: string[]) {
		const safeTxt: string[] = [];
		data.forEach((txt) => {
			if (txt !== null && txt !== undefined && txt !== '') {
				return safeTxt.push(txt);
			}
		});
		return safeTxt.join(delimiter);
	}

	/**
	 * Shows time
	 *
	 * @param from
	 * @param [to]
	 * @returns
	 */
	public showTime(from: string, to?: string) {
		const timeStr: string[] = [];
		if (from !== undefined) {
			if (from !== null && from !== '') {
				if (!from.includes(':')) {
					timeStr.push(from.substring(0, 2) + ':' + from.substring(2, 4));
				} else {
					timeStr.push(from);
				}
			} else {
				timeStr.push('');
			}
		}
		if (to !== undefined) {
			if (to !== null && to !== '') {
				if (!to.includes(':')) {
					timeStr.push(to.substring(0, 2) + ':' + to.substring(2, 4));
				} else {
					timeStr.push(to);
				}
			} else {
				timeStr.push('');
			}
		}
		return timeStr.join('~');
	}

	/**
	 * Gets assets
	 *
	 * @param url
	 * @returns
	 */
	public getAssets(url: string) {
		return this.publicPath + url;
	}
}

export default UtilsService.getInstance();
