func pinyinifyLookupHandler(writer http.ResponseWriter, request *http.Request) {
	text := getLastPathComponent(request)

	charSet := cedict.DetermineCharSet(text)
	splitText, err := chinese.SplitChineseTextIntoWords(text, charSet)
	if err != nil {
		fmt.Fprint(writer, `{"error": "`+err.Error()+`}`)
		return
	}

	output := ""

	for _, word := range splitText {
		records, _ := cedict.FindRecords(word, charSet)

		if len(records) > 0 {
			output += records[0].Pinyin
		} else {
			output += word
		}

		output += " "
	}

	j, err := json.Marshal(map[string]interface{}{
		"error":  "nil",
		"result": output,
	})
	if err != nil {
		fmt.Fprint(writer, `{"error": "`+err.Error()+`}`)
		return
	}

	fmt.Fprint(writer, string(j))
}
// TODO improve this function by always choosing the simpler
//      character when there are multiple records
func convertBetweenCharSets(text string, conversionTarget chinese.CharSet) (string, error) {
	if DetermineCharSet(text) == conversionTarget {
		return text, nil
	}

	var conversionOrigin chinese.CharSet
	if conversionTarget == chinese.Simp {
		conversionOrigin = chinese.Trad
	} else {
		conversionOrigin = chinese.Simp
	}

	t, err := chinese.SplitChineseTextIntoWords(text, conversionOrigin)
	if err != nil {
		return "", err
	}

	// turn t into a string
	output := ""
	for _, w := range t {
		records, _ := FindRecords(w, conversionOrigin)
		if len(records) == 0 {
			output += w
		} else {
			output += records[0].WordByCharSet(conversionTarget)
		}
	}

	return output, nil

}
func mcdsLookupHandler(writer http.ResponseWriter, request *http.Request) {
	text := getLastPathComponent(request)
	text = strings.Replace(text, "@SLASH@", "/", -1)
	text = strings.Replace(text, "\n", "<br />", -1)
	text = strings.Replace(text, "\t", "&nbsp;&nbsp;&nbsp;&nbsp;", -1)

	notes := request.FormValue("notes")
	notes = strings.Replace(notes, "@SLASH@", "/", -1)
	notes = strings.Replace(notes, "\n", "<br />", -1)
	notes = strings.Replace(notes, "\t", "&nbsp;&nbsp;&nbsp;&nbsp;", -1)

	charsRaw := request.FormValue("chars")
	charsArrayRaw := strings.Split(charsRaw, " ")
	// Construct new slice without empty strings
	chars := make([]string, 0)
	for _, char := range charsArrayRaw {
		if char != "" {
			chars = append(chars, char)
		}
	}

	colors := getColors(request)

	charSet := cedict.DetermineCharSet(text)
	splitText, err := chinese.SplitChineseTextIntoWords(text, charSet)
	if err != nil {
		fmt.Fprint(writer, `{"error": "`+err.Error()+`}`)
		return
	}

	var output string

	// Go through all chars to be clozed. Every iteration adds one line to the output var (i.e. one card)
	for _, char := range chars {
		var front, back string
		wordsToBeLookedUp := make([]string, 0)

		// This loop goes through all words in the text. This could be optimised by only going
		// through the text once and constructing all cards simultaneously
		for _, wordInText := range splitText {
			indexOfChar := strings.Index(wordInText, char)
			if indexOfChar == -1 {
				front += wordInText
				back += wordInText
			} else {
				front += strings.Replace(wordInText, char, clozeBegin+clozeChar+clozeEnd, -1)
				back += strings.Replace(wordInText, char, clozeBegin+char+clozeEnd, -1)

				wordsToBeLookedUp = append(wordsToBeLookedUp, wordInText)
			}
		}

		// Fine unique words to be looked up in moedict
		wordsToBeLookedUnique := make([]string, 0)
		for _, word := range wordsToBeLookedUp {
			alreadyInWordsToBeLookedUpUnique := false
			for _, wordUnique := range wordsToBeLookedUnique {
				if word == wordUnique {
					alreadyInWordsToBeLookedUpUnique = true
				}
			}
			if !alreadyInWordsToBeLookedUpUnique {
				wordsToBeLookedUnique = append(wordsToBeLookedUnique, word)
			}
		}

		cedictRecords := make([]cedict.Record, 0)
		for _, wordToBeLookedUpInCedict := range wordsToBeLookedUnique {
			records, _ := cedict.FindRecords(wordToBeLookedUpInCedict, charSet)
			for _, record := range records {
				cedictRecords = append(cedictRecords, record)
			}
		}

		moeEntries, err := findMoeEntriesForWords(wordsToBeLookedUnique, charSet)
		if err != nil {
			fmt.Fprint(writer, `{"error": "`+err.Error()+`}`)
			return
		}

		output += front
		output += "\t"
		output += back
		output += "\t"
		output += notes
		output += "\t"

		for _, moeEntry := range moeEntries {
			output += moeEntry.ToHTML(colors)
			output += "<br>"
		}

		output += "\t"

		for _, cr := range cedictRecords {
			output += cr.ToHTML(colors)
			output += "<br>"
		}

		output += "\n"
	}

	// TODO turn this into a function

	// use json.Marshal with an anonymous variable to escape the \t and " characters
	// in the response
	j, err := json.Marshal(map[string]interface{}{
		"error":  "nil",
		"result": output,
	})
	if err != nil {
		fmt.Fprint(writer, `{"error": "`+err.Error()+`}`)
		return
	}

	fmt.Fprint(writer, string(j))

}