classdef lang2_meaning

    properties (Constant)
        lex = ["owl",  "rose",  "cat",  "bot", "my", "heat", "toad", "basin", "bar", "slave", "∅"]
        gen = ["F", "M", "PL", "∅"]
        n_lex = size(lang2_meaning.lex, 2) - 1
        n_gen = size(lang2_meaning.gen, 2) - 1
        n_semantic_nodes = lang2_meaning.n_lex + lang2_meaning.n_gen
        
        all_meanings = lang2_meaning.get_list_of_all_meanings % array 3 x n_meanings
        n_meanings = size(lang2_meaning.all_meanings, 2) - 1
    end

    properties (SetAccess = immutable)
        lex_index
        gen_index
    end

    methods
        function obj = lang2_meaning(lex_logical_vector, gen_logical_vector)
            % lex
            obj.lex_index = find(lex_logical_vector, 1, 'first');
            % for NONE
            if isempty(obj.lex_index)
                obj.lex_index = obj.n_lex + 1;
            end
            
            % gen
            obj.gen_index = find(gen_logical_vector, 1, 'first');
            % for NONE
            if isempty(obj.gen_index)
                obj.gen_index = obj.n_gen + 1;
            end
        end

        function am_index = all_meanings_index(obj)
            % all_meanings
            l = lang2_meaning.lex(obj.lex_index);
            g = lang2_meaning.gen(obj.gen_index);
            am_index = find(strcmp(lang2_meaning.all_meanings(2,:), l) ...
                 & strcmp(lang2_meaning.all_meanings(3, :), g), ...
                 1, "first");
        end

        function m_vector = create_input_vector(obj)
            m_vector = lang2_meaning.create_custom_input_vector(obj.lex_index, obj.gen_index);
        end 
        
        function m_vector = create_lex_input_vector(obj)
            m_vector = zeros(1, lang2_meaning.n_semantic_nodes);
        
            if obj.lex_index <= lang2_meaning.n_lex
                lex_vector = zeros(1, lang2_meaning.n_semantic_nodes);
                lex_vector(obj.lex_index) = 1;
                m_vector = m_vector + 5.5 * lex_vector - 1.0;
            end

            m_vector(1, lang2_meaning.n_lex + 1:lang2_meaning.n_semantic_nodes) = 0;
        end 
        
        function m_vector = create_gen_input_vector(obj)
            m_vector = zeros(1, lang2_meaning.n_semantic_nodes);
        
            if obj.gen_index <= lang2_meaning.n_gen
                gen_vector = zeros(1, lang2_meaning.n_semantic_nodes);
                gen_vector(lang2_meaning.n_lex + obj.gen_index) = 1;
                m_vector = m_vector + 5.5 * gen_vector - 1.0;
            end

            m_vector(1, 1:lang2_meaning.n_lex) = 0;
        end 
    end

    methods (Static)
        function meaning = get_meaning_by_index(all_m_index)
            m_cell_array = enumeration('lang2_meaning');
            meaning = m_cell_array(all_m_index);
        end
        
        function all_meanings = get_list_of_all_meanings()
            m_cell_array = enumeration('lang2_meaning');
            
            n_meanings = size(m_cell_array, 1);
            all_meanings = strings(3, n_meanings);
            
            for i = 1:n_meanings
                meaning = m_cell_array(i);
                l = lang2_meaning.lex(meaning.lex_index);
                g = lang2_meaning.gen(meaning.gen_index);
                
                all_meanings(1, i) = strcat(l, ".", g);
                all_meanings(2, i) = l;
                all_meanings(3, i) = g;
            end
        end

        function m_vector = create_custom_input_vector(lex_index, gen_index)
            m_vector = zeros(1, lang2_meaning.n_semantic_nodes);
        
            if lex_index <= lang2_meaning.n_lex
                lex_vector = zeros(1, lang2_meaning.n_semantic_nodes);
                lex_vector(lex_index) = 1;
                m_vector = m_vector + 5.5 * lex_vector - 1.0;
            end
        
            if gen_index <= lang2_meaning.n_gen
                gen_vector = zeros(1, lang2_meaning.n_semantic_nodes);
                gen_vector(lang2_meaning.n_lex + gen_index) = 1;
                m_vector = m_vector + 5.5 * gen_vector - 1.0;
            end
        end 

        function m_vector = create_custom_input_vector_for_drawing(lex_index, gen_index)
            m_vector = zeros(1, lang2_meaning.n_semantic_nodes);
        
            if lex_index <= lang2_meaning.n_lex
                lex_vector = zeros(1, lang2_meaning.n_lex);
                lex_vector(lex_index) = 1;
                m_vector(1:lang2_meaning.n_lex) = 5.5 * lex_vector - 1.0;
            end
        end 

        function draw_zero_input()
            draw.meaning(zeros(1, lang2_meaning.n_semantic_nodes), draw.lang2_meaning_input)
        end

        function draw_zero_output()
            draw.meaning(zeros(1, lang2_meaning.n_semantic_nodes), draw.lang2_meaning_output);
        end
       
        function draw_input(meaning_input_vector)
            assert(lang2_meaning.n_semantic_nodes == size (meaning_input_vector, 2), ...
                "incorrect meaning_input_vector size")
            draw.meaning(meaning_input_vector, draw.lang2_meaning_input)
        end

        function draw_output(meaning_output_vector)
            assert(lang2_meaning.n_semantic_nodes == size (meaning_output_vector, 2), ...
                "incorrect meaning_output_vector size")
            draw.meaning(meaning_output_vector, draw.lang2_meaning_output);
        end
    end 
   
    enumeration
        SOVA  ([1 0 0 0 0 0 0 0 0 0], [1 0 0])
        SOVY  ([1 0 0 0 0 0 0 0 0 0], [0 0 1])
        ROZA  ([0 1 0 0 0 0 0 0 0 0], [1 0 0])
        ROZY  ([0 1 0 0 0 0 0 0 0 0], [0 0 1])
        KOT   ([0 0 1 0 0 0 0 0 0 0], [0 1 0])
        KOTY  ([0 0 1 0 0 0 0 0 0 0], [0 0 1])
        BOT   ([0 0 0 1 0 0 0 0 0 0], [0 1 0])
        BOTY  ([0 0 0 1 0 0 0 0 0 0], [0 0 1])
        MOJA  ([0 0 0 0 1 0 0 0 0 0], [1 0 0])
        MOJ   ([0 0 0 0 1 0 0 0 0 0], [0 1 0])
        MOJY  ([0 0 0 0 1 0 0 0 0 0], [0 0 1])
        ZHARA ([0 0 0 0 0 1 0 0 0 0], [1 0 0])
        ZHAR  ([0 0 0 0 0 1 0 0 0 0], [0 1 0])
        ZHABA ([0 0 0 0 0 0 1 0 0 0], [1 0 0])
        ZHABY ([0 0 0 0 0 0 1 0 0 0], [0 0 1])
        TAZ   ([0 0 0 0 0 0 0 1 0 0], [0 1 0])
        TAZY  ([0 0 0 0 0 0 0 1 0 0], [0 0 1])
        BAR   ([0 0 0 0 0 0 0 0 1 0], [0 1 0])
        BARY  ([0 0 0 0 0 0 0 0 1 0], [0 0 1])
        RABA  ([0 0 0 0 0 0 0 0 0 1], [1 0 0])
        RAB   ([0 0 0 0 0 0 0 0 0 1], [0 1 0])
        RABY  ([0 0 0 0 0 0 0 0 0 1], [0 0 1])
        NONE  ([0 0 0 0 0 0 0 0 0 0], [0 0 0])
    end
end
