// Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SUGGEST_SUGGEST_H_
#define SUGGEST_SUGGEST_H_

#include <string>
#include <list>
#include <vector>

#include "types.h"

#define SUGGEST_EXPORT __attribute__((visibility("default")))

namespace suggest {

class SuggestEngine;
class SuggestEngineSession;

// Description of a key.
// The coordinate system can be chosen by the user of this library,
// but keep in mind that all calculations are made in integer arithmetics.
// the rectangle is defined as location of the top left corner and size.
struct Key {
	SUGGEST_EXPORT Key() {}
	SUGGEST_EXPORT Key(vec2f location, vec2f size, charcode _code) :
		rect(location, size), code(_code) {
	}

	rect2f rect;
	charcode code;

	static Key InvalidKey;
};

// A single word suggestion including confidences
struct Suggestion {
	std::string word;
	int frequency;
	int commit_first_word_confidence;
};

// Next to the coordinates of a touch, suggest needs to know which
// character your keyboard recognized and displays to the users.
struct Touch {
	SUGGEST_EXPORT Touch() {}
	SUGGEST_EXPORT Touch(vec2f pos, charcode code);

	// create touch based on location only. Looks up which key is
	// at this location.
	SUGGEST_EXPORT Touch(vec2f pos, const SuggestEngine& engine);

	// create a touch based on char code, assumes the key is hit right at
	// the center.
	SUGGEST_EXPORT Touch(charcode code, const SuggestEngine& engine);

	vec2f pos;
	charcode code;
};

// Parameters to tweak the suggestion process.
// The list of parameters might change during iterations of the
// library, but the constructor will always choose sane default values.
// The provided locale name will be used to pick the right dictionary
// from /usr/share/libsuggest/
struct SuggestParameters {
	SUGGEST_EXPORT SuggestParameters(std::string locale);

	vec2f grid_cells;
	float search_box_size_factor;
	std::string locale;
};

// I am not 100% sure what the session concept in AOSP is used for,
// so far I have been using a single session for all suggestions.
// The session allows you to receive suggestions based on a list
// of touch coordinates and (optional) the previously typed word.
class SuggestSession {
  public:
	virtual const std::list<Suggestion>& GetSuggestions(
			const std::vector<Touch> &touches,
			std::string previous_word="") = 0;
};

// Main class of the suggestion process, which builds the keyboard definition
// and allows suggest sessions to be created with this keyboard.
class SuggestEngine {
  public:
  	virtual Key GetKeyAt(vec2f pos) const = 0;
  	virtual Key GetKey(charcode code) const = 0;

  	// start a new session
  	virtual bool LoadDictionary(std::string locale) = 0;
  	virtual SuggestSession* NewSession() = 0;
};

// To hide the implementation details of the SuggestEngine class
// (especially for hiding the AOSP API)
SUGGEST_EXPORT
SuggestEngine* NewSuggestEngine(vec2f keyboard_size, vec2f common_key_size,
						        const std::vector<Key> &keylist,
						        const SuggestParameters &parameters);


}  // namespace suggest

#endif  // SUGGEST_SUGGEST_H_