import AjaxErrorHandler from '../../assets/js/errorHandler'

const state = {
	thread: '',
	category: null,
	threadId: undefined,
	PollQuestionId: null,
	posts: [],
	postNotification: null,
	locked: false,
	reply: {
		username: '',
		id: null
	},
	editor: {
		show: false,
		loading: false,
		value: ''
	},
	mentions: [],
	loadingPosts: false,
	nextURL: '',
	previousURL: '',
	nextPostsCount: 10,
	previousPostsCount: 0,
	totalPostsCount: 0,
	selectedPosts: [],
	removePostsButtonLoading: false,
	showRemovePostsButton: false
}

const getters = {
	sortedPosts (state) {
		return state.posts.sort((a, b) => {
			return new Date(a.createdAt) - new Date(b.createdAt)
		})
	}
}

const actions = {
	deleteThread ({ state }, vue) {
		vue.axios
			.delete(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'forums/thread/' + state.threadId)
			.then(() => {
				vue.$router.push('/')
			})
			.catch(AjaxErrorHandler(vue.$store))
	},
	removePostsAsync ({ state, commit }, vue) {
		commit('setRemovePostsButtonLoading', true)

		let promises = state.selectedPosts.map(id => vue.axios.delete(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'forums/post/' + id))

		Promise.all(promises)
			.then(() => {
				commit('setRemovePostsButtonLoading', false)
				commit('setShowRemovePostsButton', false)

				state.posts = state.posts.map(post => {
					if(state.selectedPosts.includes(post.id)) {
						post.content = '<p>[This post has been removed by an administrator]</p>'
					}

					return post
				})
				state.selectedPosts = []
			})
			.catch(e => {
				commit('setRemovePostsButtonLoading', false)
				commit('setShowRemovePostsButton', false)
				AjaxErrorHandler(vue.$store)(e)
			})
	},
	addPostAsync ({ state, commit }, vue) {
		let content = state.editor.value
		state.mentions.forEach(mention => {
			let regexp = new RegExp('(^|\\s)@' + mention + '($|\\s)')
			content = content.replace(regexp, `$1[@${mention}](https://kaverti.com/u/${mention})$2`)
		})

		var post = {
			content,
			mentions: state.mentions,
			threadId: +vue.$route.params.id
		};

		if(state.reply.id) {
			post.replyingToId = state.reply.id;
		}

		commit('setThreadEditorLoading', true)

		vue.axios
			.post(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'forums/post', post)
			.then(res => {
				commit('setThreadEditorLoading', false)
				commit('addPost', res.data);
				commit('addReplyBubble', res.data)
				commit('setThreadEditorValue', '');
				commit('setThreadEditorState', false);
				commit('setTotalPostsCount', state.totalPostsCount+1)
				commit({
					type: 'setReply',
					username: '',
					id: ''
				});
			})
			.catch(e => {
				commit('setThreadEditorLoading', false)
				AjaxErrorHandler(vue.$store)(e)
			})
	},
	loadInitialPostsAsync ({ commit, dispatch }, vue) {
		commit('setPosts', [])
		commit('setThread', { name: 'Loading...' })
		dispatch('setTitle', 'Loading...')

		let postNumber = vue.$route.params.post_number
		let apiURL = process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'forums/thread/' + vue.$route.params.id

		if(postNumber !== undefined) {
			apiURL += '?postNumber=' + postNumber
		}

		vue.axios
			.get(apiURL)
			.then(res => {

				commit('setThread', res.data)
				dispatch('setTitle', res.data.name)
				commit('setNextURL', res.data.meta.nextURL)
				commit('setLocked', res.data.locked)
				commit('setPreviousURL', res.data.meta.previousURL)
				commit('setNextURL', res.data.meta.nextURL)
				commit('setPreviousURL', res.data.meta.previousURL)
				commit('setPostCounts', res.data.meta)
				commit('setTotalPostsCount', res.data.postsCount)
				commit('setPosts', res.data.Posts)

				vue.$router.replace({ name: 'thread-post', params: {
					post_number: postNumber || 0,
					slug: res.data.slug
				}});

				if(postNumber !== undefined) {
					vue.highlightPost(+postNumber)
				}
			}).catch(e => {
				if(e.response.status === 400) {
					commit('set404Page', true)
				} else {
					AjaxErrorHandler(vue.$store)(e)
				}
			})
	},
	loadPostsAsync ({ state, commit }, { vue, previous }) {
		let URL

		if(previous) {
			commit('setLoadingPostsState', 'previous')
			URL = state.previousURL
		} else {
			commit('setLoadingPostsState', 'next')
			URL = state.nextURL
		}

		if(URL === null) {
			commit('setLoadingPostsState', false)
		} else {
			vue.axios
				.get(URL)
				.then(res => {
					let currentPostsIds = state.posts.map(p => p.id)
					let filteredPosts =
						res.data.Posts.filter(p => !currentPostsIds.includes(p.id))

					commit('setLoadingPostsState', false)

					if(previous) {
						let last = filteredPosts.slice(-1)[0]

						commit('prependPosts', filteredPosts)
						commit('setPreviousURL', res.data.meta.previousURL)

						if(last) {
							vue.scrollTo(last.postNumber)
						}
					} else {
						commit('addPost', filteredPosts)
						commit('setNextURL', res.data.meta.nextURL)
					}

					commit('setPostCounts', res.data.meta)
				})
				.catch((e) => {
					console.log(e)
					AjaxErrorHandler(vue.$store)
				})
		}
	},
	loadNewPostsSinceLoad ({ state,  commit }, post) {
		if(state.nextPostsCount < 10) {
			let nextURL = state.nextURL
			let baseURL = process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'forums/thread/' + state.threadId + '?limit=10&from='

			commit('incrementNextPostsCount')

			if(nextURL === null) {
				commit('setNextURL', baseURL + (post.postNumber-1))
			}
		}
	},
	setThreadLockedState ({ state, commit }, vue) {
		vue.axios
			.put(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'forums/thread/' + state.threadId, { locked: !state.locked })
			.then(() => {
				commit('setLocked', !state.locked)
			})
			.catch((e) => {
				console.log(e)
				AjaxErrorHandler(vue.$store)
			})
	}
}

const mutations = {
	setReply (state, payload) {
		state.reply.username = payload.username;
		state.reply.id = payload.id;

		if(payload.quote) {
			state.editor.value = payload.quote;
		}
	},
	'thread/setPostNotification': (state, post) => {
		state.postNotification = post
	},
	addPost (state, post) {
		if(Array.isArray(post)) {
			state.posts.push(...post)
		} else {
			state.posts.push(post)
		}
	},
	prependPosts (state, posts) {
		state.posts.unshift(...posts)
	},
	addReplyBubble (state, post) {
		let repliedToPost = {}, index

		if(post.replyId) {
			state.posts.forEach((p, i) => {
				if(p.id === post.replyId) {
					index = i
					repliedToPost = p
				}
			})

			repliedToPost.Replies.push(post)

			state.posts.splice(index, 1, repliedToPost)
		}
	},
	setThreadEditorValue (state, value) {
		state.editor.value = value
	},
	setThreadEditorLoading (state, value) {
		state.editor.loading = value
	},
	setThreadEditorState (state, value) {
		state.editor.show = value
	},
	setLoadingPostsState (state, value) {
		state.loadingPosts = value
	},
	setPosts (state, value) {
		state.posts = value
	},
	setThread (state, obj) {
		state.thread = obj.name
		state.threadId = obj.id
		state.PollQuestionId = obj.PollQuestionId
		state.category = obj.Category
	},
	setNextURL (state, URL) {
		state.nextURL = URL
	},
	setPreviousURL (state, URL) {
		state.previousURL = URL
	},
	setPostCounts (state, meta) {
		state.previousPostsCount = meta.previousPostsCount
		state.nextPostsCount = meta.nextPostsCount
	},
	setTotalPostsCount (state, count) {
		state.totalPostsCount = count
	},
	incrementNextPostsCount (state) {
		state.nextPostsCount++
	},
	setMentions (state, mentions) {
		state.mentions = mentions
	},
	setLocked (state, value) {
		state.locked = value
	},
	setSelectedPosts (state, id ) {
		let index = state.selectedPosts.indexOf(id)

		if(index > -1) {
			state.selectedPosts.splice(index, 1)
		} else {
			state.selectedPosts.push(id)
		}
	},
	setRemovePostsButtonLoading (state, value) {
		state.removePostsButtonLoading = value
	},
	setShowRemovePostsButton (state, value) {
		state.showRemovePostsButton = value
	}
}

export default {
	state,
	getters,
	actions,
	mutations
}
