classdef draw
    
    properties (Constant)
        path_images = config.getInstance.path_images
        image_type = "png"
                
        lang1_vowel_input = "lang1_vowel_input"
        lang1_vowel_output = "lang1_vowel_output"

        lang1_meaning_input = "lang1_meaning_input"
        lang1_meaning_output = "lang1_meaning_output"
               
        lang2_vowel1_input = "lang2_vowel1_input"
        lang2_vowel1_output = "lang2_vowel1_output"
        lang2_consonant1_input = "lang2_consonant1_input"
        lang2_consonant1_output = "lang2_consonant1_output"
        lang2_vowel2_input = "lang2_vowel2_input"
        lang2_vowel2_output = "lang2_vowel2_output"
        lang2_consonant2_input = "lang2_consonant2_input"
        lang2_consonant2_output = "lang2_consonant2_output"

        lang2_meaning_input = "lang2_meaning_input"
        lang2_meaning_output = "lang2_meaning_output"
        
        lang1_dbm = "lang1_dbm"
        lang2_dbm = "lang2_dbm"
        lang1_trained_dbm = "lang1_trained_dbm"
        lang2_trained_dbm = "lang2_trained_dbm"

        dpi = 300.0
        bgcolor = 'white'
        margin = 0
        io_pad = "0.1, 0.5"
        dbm_pad = "0.1, 0.5"
        node_shape = 'circle'
        io_node_width = 0.13
        dbm_node_width = 0.13 %0.2
        node_penwidth = 0.5
        node_colorscheme = 'rdbu11'
        node_style = 'filled'
        fontname = 'Georgia'
        fontcolor = 'black'
        io_fontsize = 14
        dbm_fontsize = 5
        node_sep = 0.001

        colors_red_blue = ["#67001f" "#b2182b" "#d6604d" "#f4a582" "#fddbc7" "#f7f7f7" ...
            "#d1e5f0" "#92c5de" "#4393c3" "#2166ac" "#053061"]

    end

    methods (Static)
        function fn = img_filename(image)
            fn = fullfile(draw.path_images, image + '.' + draw.image_type);
        end

        function fn = dot_filename(image)
            fn = fullfile(draw.path_images, image + '.dot');
        end

        function fn = svg_filename(image)
            fn = fullfile(draw.path_images, image + '.svg');
        end

        function full_str = make_component_image(specific_str, filename)
            full_str = "graph G {\n" ...
            + "bgcolor=""" + draw.bgcolor + """\n" ...
            + "margin=" + draw.margin + "\n" ...
            + "pad=""" + draw.io_pad + """\n" ...
            + "node[label="""", " ...
                + "shape=""" + draw.node_shape + """, " ...
                + "width=" + draw.io_node_width + ", " ...
                + "penwidth=" + draw.node_penwidth + ", " ... 
                + "fontname=""" + draw.fontname + """\n" ...
                + "fontcolor=""" + draw.fontcolor + """\n" ...
                + "fontsize=" + draw.io_fontsize + "\n" ...
                + "style=""" + draw.node_style + """]\n" ...
            + "nodesep=" + draw.node_sep +"\n" ...
            + specific_str ...
            + "}\n";
%                + "colorscheme=" + draw.node_colorscheme + ", "... 

            draw.write_to_file(full_str, filename)
        end

        function full_str = make_dbm_image(specific_str, filename)
            full_str = "graph G {\n" ...
            + "outputorder=""edgesfirst""\n" ...
            + "ranksep=""1.2 equally""\n" ...
            + "bgcolor=""" + draw.bgcolor + """\n" ...
            + "margin=" + draw.margin + "\n" ...
            + "pad=""" + draw.dbm_pad + """\n" ...
            + "node[label="""", " ...
                + "shape=""" + draw.node_shape + """, " ...
                + "width=" + draw.dbm_node_width + ", " ...
                + "penwidth=" + draw.node_penwidth + ", " ... 
                + "fontname=""" + draw.fontname + """\n" ...
                + "fontcolor=""" + draw.fontcolor + """\n" ...
                + "fontsize=" + draw.dbm_fontsize + "\n" ...
                + "ordering=in" + "\n" ...
                + "style=""" + draw.node_style + """]\n" ...
            + "nodesep=" + draw.node_sep +"\n" ...
            + specific_str ...
            + "}\n";
            draw.write_to_file(full_str, filename)
        end

        function write_to_file(full_str, filename)
            filename_dot = draw.dot_filename(filename);
            f_image = fopen(filename_dot, 'w');
            fprintf(f_image, full_str);
            fclose(f_image);
        
            system(config.path_dot + " -q " + filename_dot + " -Gdpi=" + draw.dpi + " -T" + draw.image_type + " -o " + draw.img_filename(filename));
            system(config.path_dot + " -q " + filename_dot + " -Tsvg -o " + draw.svg_filename(filename));
        end

        function vowel(vowel_vector, filename)
            draw.make_component_image(draw.make_vowel_component(vowel_vector, "v", draw.io_fontsize), filename);
        end

        function consonant(consonant_vector, filename)        
            draw.make_component_image(draw.make_consonant_component(consonant_vector, "c"), filename);
        end

        function meaning(meaning_vector, filename)        
            draw.make_component_image(draw.make_meaning_component(meaning_vector), filename);
        end

        function dbm(activities, weights, filename)
            % hidden level 2
            n_nodes_h2 = size(activities{3}, 2);
            colors_h2 = dec2hex(int64(255 - activities{3} .* 255), 2);

            str = "\tsubgraph h2 {\n";
            for i=1:n_nodes_h2
                color = strcat("#FF", colors_h2(i, :), colors_h2(i, :));
                str = str + "\t\th2" + i + "[fillcolor=""" + color + """, fixedsize=true, label=" + i + "] \n";
                % adding labels here:, label=" + i + "
            end
            str = str + "\t}\n";
        
            % hidden level 1
            n_nodes_h1 = size(activities{2}, 2);
            colors_h1 = dec2hex(int64(255 - activities{2} .* 255), 2);

            str = str + "\tsubgraph h1 {\n";
            for i=1:n_nodes_h1
                color = strcat("#FF", colors_h1(i, :), colors_h1(i, :));
                str = str + "\t\th1" + i + "[fillcolor=""" + color + """, fixedsize=true, label=" + i + "] \n";
                % adding labels here:, label=" + i + "
            end
            str = str + "\t}\n";

            % connections between h1 and h2
            min_w2 = min(weights{2}, [],"all");
            max_w2 = max(weights{2}, [],"all");
            range_w2 = max([abs(min_w2) max_w2]);
            colors_weights_2 = int64((weights{2}) .* 5 ./ range_w2) + 6;
            
            for i=1:n_nodes_h2
                for j=1:n_nodes_h1
                    color = colors_weights_2(j, i);
                    color = draw.colors_red_blue(12-color);
                    str = str + "h2" + i + " -- h1" + j + " [penwidth=0.3 color=""" + color + "50""]\n";
                end
            end
                
            % visual level
            n_nodes_v = size(activities{1}, 2);
            nodes_v = activities{1};
            min_w1 = min(weights{1}, [],"all");
            max_w1 = max(weights{1}, [],"all");
            range_w1 = max([abs(min_w1) max_w1]);
            colors_weights_1 = int64((weights{1}) .* 5 ./ range_w1) + 6;

            % Language 1
            if n_nodes_v == lang1.n_input_nodes
                % nodes
                [v_vector, m_vector] = lang1.split_utterance_vector(nodes_v);
                str = str + draw.make_vowel_component(v_vector, "v", 9);
                str = str + draw.make_meaning_component(m_vector);
                str = str + ...
                    "fictive1[style=""invis""]\n" + ...
                    "{\n" + ...
                    "\trank=same;\n" + ...
                    "\tedge[style=invis];\n" + ...
                    "\tv1";
                    
                for i=2:size(v_vector, 2)
                    str = str + " -- v" + int2str(i);
                end
                str = str + " -- fictive1";
                for i=1:size(m_vector, 2)
                    str = str + " -- m" + int2str(i);
                end
                str = str + ";\n\trankdir=LR;\n}\n\n";

                % connections
                for i=1:n_nodes_h1
                    for j=1:size(v_vector, 2)
                        color = colors_weights_1(j, i);
                        color = draw.colors_red_blue(12-color);
                        str = str + "h1" + i + " -- v" + j + " [penwidth=0.3 color=""" + color + "50""]\n";
                    end
                    for j=1:size(m_vector, 2)
                        j_new = size(v_vector, 2) + j;
                        color = colors_weights_1(j_new, i);
                        color = draw.colors_red_blue(12-color);
                        str = str + "h1" + i + " -- m" + j + " [penwidth=0.3 color=""" + color + "50""]\n";
                    end
                end

            % Language 2
            elseif n_nodes_v == lang2.n_input_nodes
                % nodes
                [s_vector, m_vector] = lang2.split_utterance_vector(nodes_v);
                [c1_vector, v1_vector, c2_vector, v2_vector] = lang2_sound.split_sound_vector(s_vector);
                str = str + draw.make_consonant_component(c1_vector, "c1");
                str = str + draw.make_vowel_component(v1_vector, "v1", 14);
                str = str + draw.make_consonant_component(c2_vector, "c2");
                str = str + draw.make_vowel_component(v2_vector, "v2", 14);
                str = str + draw.make_meaning_component(m_vector);
                str = str + ...
                    "fictive1[style=""invis""]\n" + ...
                    "fictive2[style=""invis""]\n" + ...
                    "fictive3[style=""invis""]\n" + ...
                    "fictive4[style=""invis""]\n" + ...
                    "{\n" + ...
                    "\trank=same;\n" + ...
                    "\tedge[style=invis];\n" + ...
                    "\tc11";
                    
                for i=2:size(c1_vector, 2)
                    str = str + " -- c1" + int2str(i);
                end
                str = str + " -- fictive1";
                for i=1:size(v1_vector, 2)
                    str = str + " -- v1" + int2str(i);
                end
                str = str + " -- fictive2";
                for i=1:size(c2_vector, 2)
                    str = str + " -- c2" + int2str(i);
                end
                str = str + "  -- fictive3";
                for i=1:size(v2_vector, 2)
                    str = str + " -- v2" + int2str(i);
                end
                str = str + "  -- fictive4";
                for i=1:size(m_vector, 2)
                    str = str + " -- m" + int2str(i);
                end
                str = str + ";\n\trankdir=LR;\n}\n\n";

                % connections
                for i=1:n_nodes_h1
                    for j=1:size(c1_vector, 2)
                        color = colors_weights_1(j, i);
                        color = draw.colors_red_blue(12-color);
                        str = str + "h1" + int2str(i) + " -- c1" + int2str(j) + " [penwidth=0.3 color=""" + color + "50""]\n";
                    end
                    for j=1:size(v1_vector, 2)
                        j_new = size(c1_vector, 2) + j;
                        color = colors_weights_1(j_new, i);
                        color = draw.colors_red_blue(12-color);
                        str = str + "h1" + int2str(i) + " -- v1" + int2str(j) + " [penwidth=0.3 color=""" + color + "50""]\n";
                    end
                    for j=1:size(c2_vector, 2)
                        j_new = size(c1_vector, 2) + size(v1_vector, 2) + j;
                        color = colors_weights_1(j_new, i);
                        color = draw.colors_red_blue(12-color);
                        str = str + "h1" + int2str(i) + " -- c2" + int2str(j) + " [penwidth=0.3 color=""" + color + "50""]\n";
                    end
                    for j=1:size(v2_vector, 2)
                        j_new = size(c1_vector, 2) + size(v1_vector, 2) + size(c2_vector, 2) + j;
                        color = colors_weights_1(j_new, i);
                        color = draw.colors_red_blue(12-color);
                        str = str + "h1" + int2str(i) + " -- v2" + int2str(j) + " [penwidth=0.3 color=""" + color + "50""]\n";
                    end
                    for j=1:size(m_vector, 2)
                        j_new = size(c1_vector, 2) + size(v1_vector, 2) + size(c2_vector, 2) + size(v2_vector, 2) + j;
                        color = colors_weights_1(j_new, i);
                        color = draw.colors_red_blue(12-color);
                        str = str + "h1" + int2str(i) + " -- m" + int2str(j) + " [penwidth=0.3 color=""" + color + "50""]\n";
                    end
                end

            else
                error("Attempting to draw DBM for unknown language with " + obj.n_visible_nodes + " input nodes")
            end

            draw.make_dbm_image(str, filename);
        end


        function str = make_vowel_component(vowel_vector, name, fs_labels)
            str = "\tsubgraph " + name + " {\n";
            for i=1:vowel.n_auditory_nodes
                activity = vowel_vector(1, i);
                if activity < -1 
                    color = draw.colors_red_blue(9);
                elseif activity < -0.66 
                    color = draw.colors_red_blue(8);
                elseif activity < -0.33
                    color = draw.colors_red_blue(7);
                elseif activity <= 0
                    color = draw.colors_red_blue(6);
                elseif activity <=1
                    color = draw.colors_red_blue(5);
                elseif activity <=2
                    color = draw.colors_red_blue(4);
                elseif activity <=3
                    color = draw.colors_red_blue(3);
                elseif activity <=4
                    color = draw.colors_red_blue(2);
                elseif activity <=5
                    color = draw.colors_red_blue(1);
                else
                    color=draw.colors_red_blue(11);
                end
                str = str + "\t\t" + name + int2str(i) + "[fillcolor=""" + color + """, fixedsize=true]; \n";
                % , color=""red""
            end
        
            dist_between_labels = vowel.dist_between_labels_erbs / vowel.erbs_per_node;
            for j=1:dist_between_labels:vowel.n_auditory_nodes
                label = vowel.fmin_erb + (j-1)*vowel.erbs_per_node;
                if mod(label,1) == 0
                    str = str + "\t\t" + name + int2str(j) + "[label=""\\n\\n" + label + """ fontsize = " + fs_labels + "];\n";
                end
            end
            
            str = str + "\t}\n";
        end

        function str = make_consonant_component(consonant_vector, name)        
            str = "\tsubgraph " + name + " {\n";
            for j=1:size(consonant_vector,2)
                activity = consonant_vector(j);
                if activity <= -1.3 
                    color = draw.colors_red_blue(9);
                elseif activity <= -0.5
                    color = draw.colors_red_blue(8);
                elseif activity <= 0.5
                    color = draw.colors_red_blue(6);
                elseif activity <= 2.0
                    color = draw.colors_red_blue(5);
                elseif activity <= 3.0
                    color = draw.colors_red_blue(4);
                elseif activity <= 4.0
                    color = draw.colors_red_blue(3);
                else
                    color = draw.colors_red_blue(2);
                end
                str = str + "\t\t" + name + int2str(j) + "[fillcolor=""" + color + """, fixedsize=true, " ...
                    + "label=""\\n\\n" + lang2_sound.cons(j) + """ fontsize = " + 14 + ", fontname=""Times-Roman""];\n";
            end
                   
            str = str + "\t}\n";
        end

        function str = make_meaning_component(meaning_vector)        
            str = "\tsubgraph m {\n";
            for j=1:size(meaning_vector,2)
                activity = meaning_vector(j);
                if activity <= -1.3 
                    color = draw.colors_red_blue(9);
                elseif activity <= -0.5
                    color = draw.colors_red_blue(8);
                elseif activity <= 0.5
                    color = draw.colors_red_blue(6);
                elseif activity <= 2.0
                    color = draw.colors_red_blue(5);
                elseif activity <= 3.0
                    color = draw.colors_red_blue(4);
                elseif activity <= 4.0
                    color = draw.colors_red_blue(3);
                else
                    color = draw.colors_red_blue(2);
                end
                str = str + "\t\tm" + int2str(j) + "[fillcolor=""" + color + """, fixedsize=true];\n";
            end
        
            str = str + "\t}\n";
        end

    end
end