This document contains some technical description about the inner working
of Talented.

While Talented is an active project and likely to change from time to time,
a large part of it's internal structure and APIs are meant to stay consistent
from release to release.

This document exist for two reasons:
* to specify what the API is supposed to do and
* to specify which part of the code is part of this consistent API.

== Templates

=== Template structure

Templates are represented as a data structure (a table).

The following attributes exists:
; name: The name of the template. It always must exist and be a string.
  For saved templates, it must match the name of the key in the saved variable
  database.

; class: The class of the template. It always must exist. Classes are the
  texture name of the class for player class and the english name of the
  unique tree for pet classes. Look at spelldata.lua for the complete list.

; code: The optional encoded form of the template. The presence of a **code**
  attribute means that the template is packed and can not be directly used in
  views.

; indexes: **[1]** (**[2]** and **[3]** for player classes) are present
  when **code** is absent. The template is then considered unpacked. Each
  indexes has a table value that contains the point attribution in each talent
  of the corresponding tree.

; talentGroup: True for templates that are representation of valid specs.
  Either the player's or its pet spec are represented with a valid **talentGroup**
  attribute. Note that for pet_current, the talentGroup attribute may change.

; pet: True for the current pet template.

; points: Description. Attribute that is generated on demand when the menu
  system tries to display a template. It contains the string that is appended to
  the name of the template (primary tree and point distribution). It is also
  automatically cleared when the template is modified.

=== Template API

; <<code lua>>local template = Talented:CreateEmptyTemplate(class)<</code>>
: create a new empty template, for the given class. A valid (//Empty// based) name will be generated.

; <<code lua>>local copy = Talented:CopyTemplate(template)<</code>>
: create a new template as a copy of the given template. A valid (//Copy of// based) name will be generated.

; <<code lua>>local template = Talented:ImportTemplate(url)<</code>>
: Try to convert the given url to a valid template. A valid (//Imported// based)
  name will be generated if the importation is possible.
  returns **nil** if no importation is possible.

; <<code lua>>Talented:OpenTemplate(template)<</code>>
: Show the given template in the main Talented view, creating it if necessary.
  This will also show the Talented frame if needed.

; <<code lua>>Talented:UpdateTemplateName(template, name)<</code>>
: Changes the name of the given template to **name**, which must be a string.
  Note that this API may fail, in which case the name will not change.

== Views

Views are UI objects that can represent a template in a particular mode.
Talented has two views. One is inside the main application window, the other
is only shown when Shift-clicking on the menu entry.

=== View structure

Views have several attributes:
; frame: parent frame of the view (can be the main Talented window or another) **read only**
; name: the name of the view. Must be unique. **read only**
; class: the class of the view. **set on :SetTemplate()**
; pet: the view is for a pet tree. **set on :SetTemplate()**
; spec: the view is for an actual spec, it can't be modified except via :LearnTalent() **set on :SetTemplate()**
; mode: view display mode. Can be "view" or "edit" **changed via :SetViewMode()**
; template: the template associated with the view **changed via :SetTemplate()**
; target: the target template associated with the view **changed via :SetTemplate()**

=== View API

; <<code lua>>local view = Talented.TalentView:new(parent, name)<</code>>
: create a new view. **parent** must be a frame, **name** must be a unique non-nil value.

; <<code lua>>view:SetTemplate(template, target)<</code>>
: Set the template shown by the given view. **template** must be a valid unpacked
  template. **target** can optionally be another unpacked template of the same
  class that will be shown as "target".

; <<code lua>>view:SetViewMode(mode, force)<</code>>
: Changes the way the view is shown. There are two possible values for **mode**:
** "edit" means the view is editable.
** "view" means the view is not editable.
 the optional argument **force** can be set to true to force the view to redraw,
 even when the mode did not change.

== Import and Export modules.

Talented import and export functionality is easily extensible.

=== Importers

You can add a new importation function by adding a new entry to the
//Talented.importers// table.

The key should be a pattern, the value should be a function taking three
parameters:

<<code lua>>
Talented.importers["www.foobar.com/%?.*"] = function (self, url, dst)
	local template = dst
	-- parse the url and fill the template
	return template
end
<</code>>

; self: Talented instance. i.e. the import function is treated as a method.
; url: The import string. It matches the given pattern. It can be something else
  than a URL.
; dst: A empty template to be filled by the import function. You must set the
  **class** attribute.

Your function must return the **dst** template on success and nil on failure.

=== Exporters

You can add a new importation function by adding a new entry to the
//Talented.exporters// table.

The key should be a descriptive name for the export type, the value should be a
function taking two parameters:

<<code lua>>
Talented.exporters["Foobar URL"] = function (self, template)
	-- convert the template to a valid url
	return url
end
<</code>>

; self: Talented instance. i.e. the import function is treated as a method.
; url: The import string. It matches the given pattern. It can be something else
  than a URL.
; dst: A empty template to be filled by the import function. You must set the
  **class** attribute.

Your function must return the generated url on success and nil on failure. Note
that your function can be called for every class (and that means also pet classes).
