<?php
/*
  +---------------------------------------------------------------------------------+
  | Copyright (c) 2013 César D. Rodas                                               |
  +---------------------------------------------------------------------------------+
  | Redistribution and use in source and binary forms, with or without              |
  | modification, are permitted provided that the following conditions are met:     |
  | 1. Redistributions of source code must retain the above copyright               |
  |    notice, this list of conditions and the following disclaimer.                |
  |                                                                                 |
  | 2. Redistributions in binary form must reproduce the above copyright            |
  |    notice, this list of conditions and the following disclaimer in the          |
  |    documentation and/or other materials provided with the distribution.         |
  |                                                                                 |
  | 3. All advertising materials mentioning features or use of this software        |
  |    must display the following acknowledgement:                                  |
  |    This product includes software developed by César D. Rodas.                  |
  |                                                                                 |
  | 4. Neither the name of the César D. Rodas nor the                               |
  |    names of its contributors may be used to endorse or promote products         |
  |    derived from this software without specific prior written permission.        |
  |                                                                                 |
  | THIS SOFTWARE IS PROVIDED BY CÉSAR D. RODAS ''AS IS'' AND ANY                   |
  | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED       |
  | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE          |
  | DISCLAIMED. IN NO EVENT SHALL CÉSAR D. RODAS BE LIABLE FOR ANY                  |
  | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES      |
  | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;    |
  | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND     |
  | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT      |
  | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS   |
  | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                     |
  +---------------------------------------------------------------------------------+
  | Authors: César Rodas <crodas@php.net>                                           |
  +---------------------------------------------------------------------------------+
*/
namespace LanguageDetector;

class Learn
{
    protected $samples = array();
    protected $callback;
    protected $config;
    protected $output = array();

    public function __construct(Config $config)
    {
        $this->config = $config;
    }

    public function addStepCallback($callback)
    {
        if (!is_callable($callback)) {
            throw new \RuntimeException("\$callback must be callable");
        }
        $this->callback = $callback;
        return $this;
    }

    public function addSample($label, $text)
    {
        if (empty($this->samples[$label])) {
            $this->samples[$label] = array();
        }
        $this->samples[$label][] = $text;
        $this->output[$label]    = array();
    }
    
    public function clear()
    {
        $this->output = array();
    }

    public function save(AbstractFormat $output)
    {
        if (empty($this->samples)) {
            throw new \Exception("You need to provide samples");
        }

        $sort     = $this->config->getSortObject();
        $max      = $this->config->maxNGram();
        $parser   = $this->config->getParser();
        $callback = $this->callback;
        foreach ($this->samples as $lang => $texts) {
            if (!empty($this->output[$lang])) {
                continue;
            }
            if ($callback) {
                $callback($lang, 'start');
            }
            $text = implode("\n", $texts);
            $pos  = 0;
            $data = array();
            $sorted = $sort->sort($parser->get($text));
            foreach (array_splice($sorted, 0, $max) as $ngram => $score) {
                $data[$ngram] = array('pos' => $pos++, 'score' => $score);
            }
            $this->output[$lang] = $data;
            if ($callback) {
                $callback($lang, 'end');
            }
        }

        $output->dump(array('config' => $this->config, 'data' => $this->output));
    }
}
