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

		this.filters = filters
		this.selectedMode = AnchorReplacer.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 full',
				message:
					'Replace full changes the whole anchor in the table to the one provided through the replacement anchor field.',
			},
			{
				value: 'replace_match',
				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 anchor.',
			},
			{
				value: 'remove_match',
				label: 'Remove match',
				message:
					'The Remove match function removes the searched word(s) from the anchors in the table, regardless of their placement in the anchor.',
			},
			{
				value: 'fix',
				label: 'Fix anchor',
				message: 'Fixing removes the unwanted character from an anchor.',
			},
			{
				value: 'unlink',
				label: 'Unlink anchor',
				message: 'Unlink removes the link attached to the anchor, leaving out the words.',
			},
		]
	}

	static get SEARCH_TYPES() {
		return [
			{
				value: 'EXACT',
				label: 'Exact anchor',
				message: 'Find a specific anchor by entering its complete string.',
			},
			{
				value: 'ANCHOR_CONTAINS',
				label: 'Anchor contains',
				message: 'Search for anchors that contain a specific string.',
			},
			{
				value: 'SHARED_TARGET',
				label: 'Shared-Target anchor',
				message:
					'Identify instances of anchors pointing to the same target URL. For example, Post A has two anchor texts linking to Post B.',
			},
			{
				value: 'DUPLICATE',
				label: 'Duplicate anchors',
				message:
					'Identify multiple instances of an anchor on a page, whether pointing to the same target URL or not.',
			},
			{
				value: 'EMPTY_ANCHOR',
				label: 'Empty anchors',
				message:
					'Find empty anchors that has a link.',
			},
			{
				value: 'STARTS_WITH',
				label: 'Starts with',
				message: 'Find anchors that start with a particular word.',
			},
			{
				value: 'ENDS_WITH',
				label: 'Ends with',
				message: 'Find anchors that ends with a particular word.',
			},
			{
				value: 'COMMA_AFTER',
				label: 'Comma after',
				message: 'Find anchors that end with unwanted commas.',
			},
			{
				value: 'COMMA_BEFORE',
				label: 'Comma before',
				message: 'Find anchors that start with unwanted commas.',
			},
			{
				value: 'SPACE_AFTER',
				label: 'Space after',
				message: 'Find anchors that end with unwanted spaces.',
			},
			{
				value: 'SPACE_BEFORE',
				label: 'Space before',
				message: 'Find anchors that start with unwanted spaces.',
			},
			{
				value: 'FULL_STOP_AFTER',
				label: 'Full stop after',
				message: 'Find anchors that end with unwanted full stops.',
			},
			{
				value: 'FULL_STOP_BEFORE',
				label: 'Full stop before',
				message: 'Find anchors that start with unwanted full stops.',
			},
		]
	}

	static get FILTER_MODES() {
		return [
			{
				placeholder: 'Source contains',
				label: 'Source contains',
				value: 'source',
			},
			{
				placeholder: 'Source is',
				label: 'Source is',
				value: 'source-is',
			},
			{
				placeholder: 'Link contains',
				label: 'Link contains',
				value: 'link',
			},
			{
				placeholder: 'Link is',
				label: 'Link is',
				value: 'link-is',
			},
			{
				placeholder: 'Anchor contains',
				label: 'Anchor contains',
				value: 'anchor',
			},	
		]
	}

	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
	}

	toPage(page) {
		this._pagination.page = page
	}

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

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

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

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

		return this._data
	}

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

		const params = urlSearchParams({
			action: `linksy_search_and_replace_${selectedAction}_anchors`,
			nonce: this._token,
			items: JSON.stringify(items),
			anchor_replacement: anchor_replacement,
			keyword: keyword,
		})

		const {
			data: { data },
		} = await axios.post(ajaxurl, params)

		return data
	}
}
