using System;
using System.Collections.Generic;
using System.Text;

namespace Intemi.InTrees
{
    #region TDIDT Algoritm elements
    public interface INodeTestGenerator : IIntemi
    {
        List<INodeTest> GenerateTests(IDataTable data, ref bool shouldTerminate);
        INodeTest GenerateBestTest(IDataTable data, INodeTestSelector testSelector, ref bool shouldTerminate);
    }

    public interface INodeTestSelector : IIntemi
    {
        INodeTest SelectTest(List<INodeTest> nodeTests, IDataTable dataTable, ref bool shouldTerminate);
        double RateTest(INodeTest nodeTests, IDataTable dataTable, ref bool shouldTerminate);
    }

    public interface IStoppingCriterion : IIntemi
    {
        bool Stop(IDataTable dataTable, List<INodeTest> nodeTests, ref bool shouldTerminate);
        bool Stop(IDataTable dataTable, ref bool shouldTerminate);
    }

    public interface ITargetSelector : IIntemi
    {
        int SelectTarget(IDataTable dataTable, int target, ref bool shouldTerminate);
    }
    #endregion 

    #region Pruning
    public interface IPruning : IIntemi
    {
        /// <summary>
        /// Przycina drzewo stosując według kryteriów zawartych w konfiguracji przycinania
        /// </summary>
        /// <param name="tree">Drzewo do przycięcia</param>
        /// <param name="config">Konfiguracja przycinania</param>
        /// <param name="shouldTerminate">Polecenie przerwania procedury</param>
        /// <returns>Przycięte drzewo</returns>
        DecisionTree Prune(DecisionTree tree, IPruningConfiguration config, IDataTable trainDT, ref bool shouldTerminate);

        /// <summary>
        /// Wskazuje optymalną konfigurację przycinania
        /// </summary>
        /// <param name="tables">Tablice zawierające kongigurację przycinania i osiągnięte przez nie wyniki klasyfikacji</param>
        /// <param name="shouldTerminate">Polecenie przerwania procedury</param>
        /// <returns>Optymalna konfiguracja</returns>
        IPruningConfiguration SelectOptimalConfiguration(List<IPruningTable> tables, ref bool shouldTerminate);

        /// <summary>
        /// Przycina drzewo w różnych konfiguracjach i zwraca tablicę zawierającą tego efekty
        /// </summary>
        /// <param name="tree">Drzewo</param>
        /// <param name="shouldTerminate">Polecenie przerwania procedury</param>
        /// <returns>Tablica zawierająca kongigurację przycinania i osiągnięte przez nie wyniki klasyfikacji</returns>
        IPruningTable BuildPruningTable(DecisionTree tree, IDataTable trainDT, IDataTable testDT, ref bool shouldTerminate);

    }

    public interface IPruningConfiguration
    {

    }

    public interface IPruningTable
    {
        //IPruningConfiguration Configuration {get;set;}
        //IPruningResult Result { get;set;}
    }
    #endregion

    public interface INodeTest : IIntemi
    {
        // List<IClassificationRule> NodeRules{get; set;}

        double TestRate { get;set;}


        void AddRule(IClassificationRule rule);
        IClassificationRule GetRule(int index);

        /// <summary>
        /// Zwraca ilość gałęzi powstałą na skutek danego testu.
        /// </summary>
        /// <returns></returns>
        int SplitCount();


        /// <summary>
        /// Określa do którego poddrzewa powstałego w wyniku testu należy dany wektor 
        /// </summary>
        /// <param name="data"></param>
        /// <param name="missing"></param>
        /// <param name="fi"></param>
        /// <returns>Numer poddrzewa (gałęzi)</returns>
        int SplitData(float[] data, bool[] missing, IFeaturesInfo fi, ref bool shouldTerminate);

        IDataTable[] SplitData(IDataTable dataTable, ref bool shouldTerminate);

        string ToString(int rule);
        string ToHtml(int rule);
        string ToString();
        string ToHtml();
    }

}
