const db           = require('./data.json');
const firebase     = require('./firebase');
const slackMessage = require('./slackMessage');
const templates    = require('./templates');

const SLOT_REGEX = /\((\w)+\)/g;
const ID_REGEX     = /(#\w+)/g;

const ALLOWED_FLAGS = [
	'id',
	'quiet'
];

function matchCardByName(query, card) {
	let isMatch = card.key.includes(query.term);

	if(isMatch && query.slot) {
		isMatch = query.slot.includes(card.slot);
	}

	return isMatch;
}

function searchForCardById(cardId) {
	return firebase.refs.cards.child(cardId)
		.once('value')
		.then((snapshot) => snapshot.val())
		.then((card) => typeof card === 'object' ? [card] : []);
}

function searchCards(query) {
	if(query.isId) {
		query.term = parseInt(query.term, 10);
		return searchForCardById(query.term);
		// return [db.find((card) => matchCardById(query, card))];
	}
	return new Promise(function(resolve) {
		resolve(db.filter((card) => matchCardByName(query, card)));
	});
}

function convertCardToResponse(card, isPrivate) {
	let responseData = {
		text:      templates.card(card),
		image:     card.image,
		isPrivate
	};

	return slackMessage(responseData);
}

function handleMultipleCards(foundCards, query) {
	return slackMessage({
		text:      templates.multiple(foundCards, query),
		isPrivate: true
	});
}

function formatSlots(slot) {
	slot = slot.replace(/\(|\)/g, '')
		.trim()
		.toLowerCase();

	if(!firebase.slots().includes(slot)) {
		slot = '';
	}

	return slot;
}

function parseSlots(queryText) {
	// Get any requested slots
	let slots   = queryText.match(SLOT_REGEX);

	if(slots) {
		slots = slots
			.map(formatSlots)
			.filter((slot) => slot.length > 0);
		// Store if we have any after filtering
		return (slots.length > 0 ? slots : false);
	}
	return false;
}

function parseFags(queryText) {
	// Get any requested filters
	let flags   = queryText.match(ID_REGEX);
	if(flags) {
		flags = flags
			.map((flag) => flag.replace('#', ''))
			.map((flag) => ALLOWED_FLAGS.includes(flag) ? flag : '')
			.filter((flag) => flag.length > 0);
		// Store if we have any after filtering
		return (flags.length > 0 ? flags : false);
	}
	return false;
}

function formatSearch(term) {
	// Make sure we only compare in lowercase
	term      = term.toLowerCase();
	let slot  = parseSlots(term);
	let flags = parseFags(term)
	// Strip the command string from the search text
	term      = term
		.replace(SLOT_REGEX, '')
		.replace(ID_REGEX, '')
		.trim();

	return {
		term,
		slot,
		isPrivate: Array.isArray(flags) && flags.includes('quiet'),
		isId:      Array.isArray(flags) && flags.includes('id')
	};
}

function handleNotFound(query) {
	return slackMessage({
		text:      templates.notFound(query),
		isPrivate: true
	});
}

function handleSearchResponse(cards, query, search) {
	const resultCount = cards.length;

	if(resultCount === 0) {
		return handleNotFound(query);
	} else if(resultCount === 1) {
		return convertCardToResponse(cards[0], search.isPrivate);
	} else {
		return handleMultipleCards(cards, query);
	}
}

module.exports = function search(query) {
	const search = formatSearch(query.text);

	return searchCards(search)
		.then((cards) => handleSearchResponse(cards, query, search));
};

@@ -681,21 +681,20 @@
 n search
-Cards
+ById
 (query) 
@@ -700,37 +700,19 @@
  %7B%0A%09
-if(query.isId) %7B%0A%09%09query.term
+const theId
  = p
@@ -736,17 +736,16 @@
 m, 10);%0A
-%09
 %09return 
@@ -766,84 +766,49 @@
 yId(
-query.term);%0A%09%09// return %5Bdb.find((card) =%3E matchCardById(query, card))%5D;%0A%09%7D
+theId);%0A%7D%0A%0Afunction searchByText(query) %7B
 %0A%09re
@@ -824,24 +824,16 @@
 Promise(
-function
 (resolve
@@ -833,16 +833,19 @@
 resolve)
+ =%3E
  %7B%0A%09%09res
@@ -901,32 +901,144 @@
 ard)));%0A%09%7D);%0A%7D%0A%0A
+function searchCards(query) %7B%0A%09if(query.isId) %7B%0A%09%09return searchById(query);%0A%09%7D%0A%0A%09return searchByText(query);%0A%7D%0A%0A
 function convert
@@ -1722,33 +1722,54 @@
 h %3E 0);%0A
+%0A
 %09%09// 
-Stor
+Return the slots or fals
 e if we 
 have any
@@ -1756,32 +1756,38 @@
 false if we 
+don't 
 have any
  after filte
@@ -1774,32 +1774,16 @@
 have any
- after filtering
 %0A%09%09retur

Split out the search methods in to different terms