// Silence may be golden, but sometimes words paint the canvas of understanding.
class TitleReplacer {
	constructor(token, filters = {}) {
		if (!token || typeof token !== 'string') {
			throw new TypeError('Token must be a string')
		}

		this.filters = filters
		this.selectedMode = TitleReplacer.FILTER_MODES[0].value

		// private methods
		this._token = token
		this._data = []
		this._pagination = {
			page: 0,
			limit: 10,
			total: 0,
			filteredTotal: 0,
		}
	}

	static get SUPPORTED_ACTIONS() {
		return [
			{
				value: 'replace',
				label: 'Replace match',
				message:
					'The Replace match function replaces the input text with the text provided in the replacement field. It does not replace the entire title.',
			},
			{
				value: 'remove',
				label: 'Remove match',
				message:
					'The Remove match function removes the searched word(s) from the titles in the table, regardless of their placement in the title.',
			},
		]
	}

	static get SEARCH_TYPES() {
		return [
			{
				value: 'EXACT',
				label: 'Exact title',
				message: 'Find a specific post title by entering it in full.',
			},
			{
				value: 'CONTAINS',
				label: 'Title contains',
				message: 'Search for post titles that include a specific word(s).',
			},
		]
	}

	static get FILTER_MODES() {
		return [
			{
				placeholder: 'Title Contains',
				label: 'Title Contains',
				value: 'title',
			},
			{
				placeholder: 'Link is',
				label: 'Link is',
				value: 'link-is',
			},
			{
				placeholder: 'Link Contains',
				label: 'Link Contains',
				value: 'link',
			},
		]
	}

	get pagination() {
		return Object.freeze({
			...this._pagination,
			total: this._pagination.filteredTotal || this._pagination.total,
		})
	}

	set pagination(value) {
		if (typeof value !== 'object') {
			throw new Error('Invalid pagination value: ' + value)
		}

		this._pagination = {
			...this._pagination,
			...value,
		}
	}

	get data() {
		return Object.freeze([...this._data])
	}

	set data(data) {
		this._data = data
	}

	reset() {
		this._data = []
		this._pagination = {
			...this._pagination,
			page: 0,
			total: 0,
			filteredTotal: 0,
		}
	}

	toPage(page) {
		if (typeof page !== 'number') {
			throw new Error('Invalid pagination page: ' + page)
		}

		this._pagination.page = page
	}

	async searchTitles(query, searchMode, filterQuery, filter) {
		this._data = []

		const params = toQueryString({
			action: 'linksy_search_and_replace_search_titles',
			nonce: this._token,
			search: encodeURIComponent(query.trim()),
			page: this._pagination.page,
			limit: this._pagination.limit,
			filter: JSON.stringify(filter),
			filter_mode: this.selectedMode,
			filter_query: filterQuery,
			search_mode: searchMode || TitleReplacer.SEARCH_TYPES[0].value,
		})

		const {
			data: { data },
		} = await axios.get(ajaxurl + '?' + params)

		// update the pagination and data
		this._pagination.total = data.total
		this._data = data.results

		return this._data
	}

	async applySelectedAction(keyword, action, items = [], title_replacement = '') {
		if (!items.length) {
			return
		}

		const params = urlSearchParams({
			action: `linksy_search_and_replace_${action}_titles`,
			nonce: this._token,
			items: JSON.stringify(items),
			title_replacement: title_replacement.trim(),
			keyword: keyword.trim(),
		})
		await axios.post(ajaxurl, params)
	}
}
