/*
    Copyright (C) 2012 Bartosz Broda, Jacek Bochenek, Łukasz Biłeńkij, 
    Damian Jaworski, Wojciech Mazur, Dominik Piasecki, Maciej Piasecki, 
    Radosław Ramocki
    
    This program is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your option)
any later version.

    This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. 

    See the LICENSE and COPYING files for more details.
*/

#ifndef LIBNERREADER_NERREADER_H
#define LIBNERREADER_NERREADER_H

#include <libcorpus2/io/reader.h>
#include "liner.h"


namespace Corpus2 {

class NERReader: public TokenReader
{
public:
	/**
	  * \param filename corpus filename (NER file is given in options)
	  */
	NERReader(const Tagset& tagset, const std::string& filename);

	~NERReader();

	/// retrieves whole sentence, finds NERs, and return tokens
	Token* get_next_token();

	/// the prefered mode for this reader
	Sentence::Ptr get_next_sentence();

	/**
	  * retrieves chunk with inner reader and then searches for NERs within
	  * sentences.
	  */
	boost::shared_ptr<Chunk> get_next_chunk();
	/**
	  * setting an "inner:..." option is equal to an immediate creation of an inner reader.
	  * If a filename set in ctor is not valid, setting the "inner" option results in error.
	  *
	 **/
	void set_option(const std::string& option);

	/**
	 * Option inspector. Should echo the option if it is set, return
	 * an empty string otheriwse, and "unknown" if the option is invalid.
	 */
	std::string get_option(const std::string& option) const;

	/**
	 * Check if the reader is valid, should throw if not. Called after
	 * all set_options during factory reader creation.
	 */
	virtual void validate();

	static bool registered;

	void change_input_file(const std::string &filename);

protected:


private:

	Sentence::Ptr process_sentence(Corpus2::Sentence::Ptr sentence);
	Sentence::Ptr proc_sentence(Corpus2::Sentence::Ptr sentence,std::vector<Liner::linerTuple> liner_out,int offset);

	std::string get_new_orth(Corpus2::Sentence::Ptr sentence,std::string name,const std::vector<int>& all);
	std::string get_new_base(Corpus2::Sentence::Ptr sentence,std::string name,const std::vector<int>& all);

	/// ptr to inner reader doing the real work of reading a corpus
	TokenReaderPtr inner_reader_;
	/// path for inner reader
	std::string inner_filename_;
	/// inner reader option
	size_t token_index;
	/// contains last processed sentence
	Sentence::Ptr currentSentence;
	/// contains last processed chunk
	boost::shared_ptr<Chunk> currentChunk;
	Tagset myTagset;

	boost::shared_ptr<Liner> liner;
	std::string nerd_path;
	std::string model_file;
	std::string liner_path;
	std::string liner_file;

	std::string inner_name;

};

} // ns Corpus2

#endif // LIBNERREADER_NERREADER_H
