classdef lang1_meaning

    properties (Constant)
        lex = ["egg", "goat", "grain", "∅"]
        gen = ["SG", "PL", "∅"]
        n_lex = size(lang1_meaning.lex, 2) - 1
        n_gen = size(lang1_meaning.gen, 2) - 1
        n_semantic_nodes = lang1_meaning.n_lex + lang1_meaning.n_gen
        
        all_meanings = lang1_meaning.get_list_of_all_meanings % array 3 x 6(including NONE)
        n_meanings = size(lang1_meaning.all_meanings, 2) - 1
    end
    
    properties (SetAccess = immutable)
        lex_index
        gen_index
    end

    methods
        function obj = lang1_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 = lang1_meaning.lex(obj.lex_index);
            g = lang1_meaning.gen(obj.gen_index);
            am_index = find(and(strcmp(lang1_meaning.all_meanings(2,:), l), ...
                 strcmp(lang1_meaning.all_meanings(3, :), g)), 1, "first");
        end

        function m_vector = create_input_vector(obj)
            m_vector = lang1_meaning.create_custom_input_vector(obj.lex_index, obj.gen_index);
        end 
    end
   
    methods (Static)
        function meaning = get_meaning_by_index(all_m_index)
            m_cell_array = enumeration('lang1_meaning');
            meaning = m_cell_array(all_m_index);
        end
        
        function all_meanings = get_list_of_all_meanings()
            m_cell_array = enumeration('lang1_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 = lang1_meaning.lex(meaning.lex_index);
                g = lang1_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, lang1_meaning.n_semantic_nodes);
        
            if lex_index <= lang1_meaning.n_lex
                lex_vector = zeros(1, lang1_meaning.n_semantic_nodes);
                lex_vector(lex_index) = 1;
                m_vector = m_vector + 5.5 * lex_vector - 1.0;
            end
        
            if gen_index <= lang1_meaning.n_gen
                gen_vector = zeros(1, lang1_meaning.n_semantic_nodes);
                gen_vector(lang1_meaning.n_lex + gen_index) = 1;
                m_vector = m_vector + 5.5 * gen_vector - 1.0;
            end
        end 

        function draw_zero_input()
            draw.meaning(zeros(1, lang1_meaning.n_semantic_nodes), draw.lang1_meaning_input)
        end

        function draw_zero_output()
            draw.meaning(zeros(1, lang1_meaning.n_semantic_nodes), draw.lang1_meaning_output);
        end
       
        function draw_input(meaning_input_vector)
            assert(lang1_meaning.n_semantic_nodes == size (meaning_input_vector, 2), ...
                "incorrect meaning_input_vector size")
            draw.meaning(meaning_input_vector, draw.lang1_meaning_input)
        end

        function draw_output(meaning_output_vector)
            assert(lang1_meaning.n_semantic_nodes == size (meaning_output_vector, 2), ...
                "incorrect meaning_output_vector size")
            draw.meaning(meaning_output_vector, draw.lang1_meaning_output);
        end
    end 
   
    enumeration
        EGG   ([1 0 0], [1 0])
        EGGS  ([1 0 0], [0 1])
        GOAT  ([0 1 0], [1 0])
        GOATS ([0 1 0], [0 1])
        GRAIN ([0 0 1], [0 0])
        NONE  ([0 0 0], [0 0])
    end
end
