import plotext_plus._utility as ut

# this file builds a class inherited by the MonitorClass() in _monitor.py just because its only method - build_plot() - is very long and it is the core of plot building and it is written separately for clarity


class BuildClass:

    def build_plot(
        self,
    ):  # it builds the plot given the external settings and internal settings collected in draw()

        # Initial Tools
        r2 = [0, 1]
        signals = len(self.x)
        signal_indices = list(range(signals))
        texts = len(self.text)
        text_indices = list(range(texts))
        width, height = self.size
        ticks_colors = self.ticks_color, self.ticks_style

        # Find if Axes are used
        xside = [
            (self.default.xside[i] in self.xside + self.txside) or self.vcoord[i] != []
            for i in r2
        ]
        yside = [
            (self.default.yside[i] in self.yside + self.tyside) or self.hcoord[i] != []
            for i in r2
        ]

        # Remove Useless X and Y Ticks and Labels if axes are not used
        self.xticks = [self.xticks[i] if xside[i] else None for i in r2]
        self.xlabels = [self.xlabels[i] if xside[i] else None for i in r2]

        self.yticks = [self.yticks[i] if yside[i] else None for i in r2]
        self.ylabels = [self.ylabels[i] if yside[i] else None for i in r2]

        # Remove Useless h and v user defined Lines if axes are not used
        self.hcoord = [self.hcoord[i] if yside[i] else [] for i in r2]
        self.vcoord = [self.vcoord[i] if xside[i] else [] for i in r2]
        self.hcolors = [self.hcolors[i] if yside[i] else [] for i in r2]
        self.vcolors = [self.vcolors[i] if xside[i] else [] for i in r2]

        # Apply Scale (linear or log) to the data
        xscale = [
            ut.get_first(self.xscale, self.xside[s] is self.default.xside[0])
            for s in signal_indices
        ]  # the x scale for each signal
        yscale = [
            ut.get_first(self.yscale, self.yside[s] is self.default.yside[0])
            for s in signal_indices
        ]  # the y scale for each signal
        self.x = [
            ut.apply_scale(self.x[s], xscale[s] is self.default.xscale[1])
            for s in signal_indices
        ]  # apply optional log scale
        self.y = [
            ut.apply_scale(self.y[s], yscale[s] is self.default.yscale[1])
            for s in signal_indices
        ]

        # Apply Scale (linear or log) to the Axes Ticks
        self.xticks = [
            (
                ut.apply_scale(self.xticks[i], self.xscale[i] is self.default.xscale[1])
                if self.xticks[i] is not None
                else None
            )
            for i in r2
        ]  # apply optional log scale
        self.yticks = [
            (
                ut.apply_scale(self.yticks[i], self.yscale[i] is self.default.yscale[1])
                if self.yticks[i] is not None
                else None
            )
            for i in r2
        ]  # apply optional log scale

        # Apply Scale (linear or log) to the user defined Lines
        self.hcoord = [
            ut.apply_scale(self.hcoord[i], self.yscale[i] is self.default.yscale[1])
            for i in r2
        ]  # apply optional log scale
        self.vcoord = [
            ut.apply_scale(self.vcoord[i], self.xscale[i] is self.default.xscale[1])
            for i in r2
        ]  # apply optional log scale

        # Apply Scale (linear or log) to the user defined Text
        txscale = [
            ut.get_first(self.xscale, self.txside[s] is self.default.xside[0])
            for s in text_indices
        ]  # the x scale for each text
        tyscale = [
            ut.get_first(self.yscale, self.tyside[s] is self.default.yside[0])
            for s in text_indices
        ]  # the y scale for each text
        self.tx = [
            ut.apply_scale([self.tx[s]], txscale[s] is self.default.xscale[1])[0]
            for s in text_indices
        ]  # if width_canvas * height_canvas > 0 else [] # apply optional log scale
        self.ty = [
            ut.apply_scale([self.ty[s]], tyscale[s] is self.default.yscale[1])[0]
            for s in text_indices
        ]  # if width_canvas * height_canvas > 0 else [] # apply optional log scale
        tx = [
            [self.tx[s] for s in text_indices if self.txside[s] is self.default.xside[i]]
            for i in r2
        ]  # text x coord for each axis
        ty = [
            [self.ty[s] for s in text_indices if self.tyside[s] is self.default.yside[i]]
            for i in r2
        ]  # text x coofor each axis

        # Get X Axes Limits
        x = [
            ut.join([self.x[s] for s in signal_indices if self.xside[s] is side])
            for side in self.default.xside
        ]  # total x data for each axis
        x = [
            x[i] + self.vcoord[i] + tx[i] for i in r2
        ]  # add v lines and text coords to calculate xlim
        xlim = [ut.get_lim(el) if len(el) > 0 else [None, None] for el in x]
        self.xlim = [ut.replace_none(self.xlim[i], xlim[i]) for i in r2]
        self.xlim = [
            self.xlim[i][:: self.xdirection[i]] for i in r2
        ]  # optionally reverse axes
        xlim = [
            self.xlim[0] if self.xside[s] == self.default.xside[0] else self.xlim[1]
            for s in signal_indices
        ]  # xlim for each signal

        # Get Y Axes Limits
        y = [
            ut.join([self.y[s] for s in signal_indices if self.yside[s] is side])
            for side in self.default.yside
        ]
        y = [
            y[i] + self.hcoord[i] + ty[i] for i in r2
        ]  # add h lines and text coords to calculate ylim
        ylim = list(map(ut.get_lim, y))
        self.ylim = [ut.replace_none(self.ylim[i], ylim[i]) for i in r2]
        self.ylim = [
            self.ylim[i][:: self.ydirection[i]] for i in r2
        ]  # optionally reverse axes
        ylim = [
            self.ylim[0] if self.yside[s] == self.default.yside[0] else self.ylim[1]
            for s in signal_indices
        ]  # ylim for each signal

        # Get Y Ticks and Labels
        yticks_to_set = [
            self.yticks[i] is None and yside[i] and len(y[i]) > 0 for i in r2
        ]
        yticks = [
            (
                ut.linspace(*self.ylim[i], self.yfrequency[i])
                if yticks_to_set[i]
                else self.yticks[i]
            )
            for i in r2
        ]  # the actual Y ticks
        yticks_rescaled = [
            ut.reverse_scale(yticks[i], self.yscale[i] is self.default.yscale[1])
            for i in r2
        ]

        ylabels = [
            (
                self.date.times_to_string(yticks_rescaled[i])
                if self.y_date[i]
                else (
                    ut.get_labels(yticks_rescaled[i])
                    if yticks_to_set[i]
                    else self.ylabels[i]
                )
            )
            for i in r2
        ]
        ylabels = [
            (
                ut.add_extra_spaces(ylabels[i], self.default.yside[i])
                if ylabels[i] is not None
                else None
            )
            for i in r2
        ]
        width_ylabels = [ut.max_length(el) if el is not None else 0 for el in ylabels]

        # Get X Ticks and Labels
        xticks_to_set = [
            self.xticks[i] is None and xside[i] and len(x[i]) > 0 for i in r2
        ]
        xticks = [
            (
                ut.linspace(*self.xlim[i], self.xfrequency[i])
                if xticks_to_set[i]
                else self.xticks[i]
            )
            for i in r2
        ]  # the actual X ticks
        xticks_rescaled = [
            ut.reverse_scale(xticks[i], self.xscale[i] is self.default.xscale[1])
            for i in r2
        ]
        xlabels = [
            (
                self.date.times_to_string(xticks_rescaled[i])
                if self.x_date[i]
                else (
                    ut.get_labels(xticks_rescaled[i])
                    if xticks_to_set[i]
                    else self.xlabels[i]
                )
            )
            for i in r2
        ]
        xlabels = [
            (
                ut.add_extra_spaces(xlabels[i], self.default.xside[i])
                if xticks_to_set[i]
                else self.xlabels[i]
            )
            for i in r2
        ]
        height_xlabels = [len(el) > 0 if el is not None else 0 for el in xlabels]

        # Canvas Dimensions (the area of data points)
        width_canvas = width - sum(self.yaxes) - sum(width_ylabels)
        height_highbar = any(el is not None for el in [self.title, self.xlabel[1]])
        height_lowbar = any(el is not None for el in self.ylabel + [self.xlabel[0]])
        height_canvas = (
            height
            - sum(self.xaxes)
            - sum(height_xlabels)
            - height_highbar
            - height_lowbar
        )

        # Canvas Offset
        col_start = width_ylabels[0] + self.yaxes[0]
        col_end = col_start + width_canvas
        row_start = height_lowbar + height_xlabels[0] + self.xaxes[0]
        row_end = row_start + height_canvas

        # Get Absolute X and Y Ticks
        cticks = [
            (
                ut.get_matrix_data(xticks[i], self.xlim[i], width_canvas)
                if xticks[i] is not None
                else []
            )
            for i in r2
        ]
        rticks = [
            (
                ut.get_matrix_data(yticks[i], self.ylim[i], height_canvas)
                if yticks[i] is not None
                else []
            )
            for i in r2
        ]

        # Get Absolute Coordinates for user defined Lines
        hticks = [
            (
                ut.get_matrix_data(self.hcoord[i], self.ylim[i], height_canvas)
                if None not in self.ylim[i]
                else []
            )
            for i in r2
        ]
        vticks = [
            (
                ut.get_matrix_data(self.vcoord[i], self.xlim[i], width_canvas)
                if None not in self.xlim[i]
                else []
            )
            for i in r2
        ]

        # Get Absolute Coordinates for user defined Text
        txlim = [
            ut.get_first(self.xlim, self.txside[s] == self.default.xside[0])
            for s in text_indices
        ]  # xlim for each text
        tylim = [
            ut.get_first(self.ylim, self.tyside[s] == self.default.yside[0])
            for s in text_indices
        ]  # xlim for each text
        tcticks = [
            (
                ut.get_matrix_data([self.tx[s]], txlim[s], width_canvas)[0]
                if width_canvas > 0
                else 0
            )
            for s in text_indices
        ]  # if width_canvas > 0 else [] #
        trticks = [
            (
                ut.get_matrix_data([self.ty[s]], tylim[s], height_canvas)[0]
                if height_canvas > 0
                else 0
            )
            for s in text_indices
        ]  # if height_canvas > 0 else [] #

        # Get effective number of User Lines
        hlines = [len(el) for el in hticks]
        hline_indices = [
            list(range(el)) for el in hlines
        ]  # number of user defined horizontal lines for each y axis (as list)
        vlines = [len(el) for el in vticks]
        vline_indices = [
            list(range(el)) for el in vlines
        ]  # number of user defined vertical lines for each x axis (as list)

        # Create Matrix of Markers
        self.matrix.set_size(width, height)
        self.matrix.set_axes_color(self.axes_color)
        self.matrix.set_canvas_area(col_start, col_end, row_start, row_end)
        self.matrix.set_canvas_color(self.canvas_color)
        self.matrix.set_matrices()

        # Add Title
        col_center = (
            col_start + width_canvas // 2
        )  # centered on the canvas not the entire plot
        col_title = col_center if self.xlabel[1] is None else 0
        row_title = row_end + self.xaxes[1] + height_xlabels[1]
        alignment_title = "center" if self.xlabel[1] is None else "left"
        (
            self.matrix.add_horizontal_string(
                col_title,
                row_title,
                self.title,
                *ticks_colors,
                alignment=alignment_title,
                check_space=True,
            )
            if self.title and height > 0
            else None
        )

        # Add Upper X Label
        (
            self.matrix.add_horizontal_string(
                col_center,
                row_title,
                self.xlabel[1],
                *ticks_colors,
                alignment="center",
                check_space=True,
            )
            if self.xlabel[1] and height > 0
            else None
        )

        # Add Lower X Ticks
        row_xticks = min(row_start - self.xaxes[0] - 1, height - 1)
        cticks_inserted = [
            height > 0
            and self.matrix.add_horizontal_string(
                col_start + cticks[0][i],
                row_xticks,
                xlabels[0][i],
                *ticks_colors,
                alignment="dynamic",
                check_space=True,
            )
            for i in range(len(cticks[0]))
        ]
        cticks[0] = [
            cticks[0][i] for i in range(len(cticks[0])) if cticks_inserted[i]
        ]  # it updates the x ticks coordinates whatever x labels were inserted

        # Add Upper X Ticks: the reason to do it here prematurely, is that the cticks[1] need to be re-evaluated for next step
        row_xticks = row_end + self.xaxes[1]
        cticks_inserted = [
            height > 0
            and self.matrix.add_horizontal_string(
                col_start + cticks[1][i],
                row_xticks,
                xlabels[1][i],
                *ticks_colors,
                alignment="dynamic",
                check_space=True,
            )
            for i in range(len(cticks[1]))
        ]
        cticks[1] = [
            cticks[1][i] for i in range(len(cticks[1])) if cticks_inserted[i]
        ]  # it updates the x ticks coordinates whatever x labels were inserted

        # Add Upper X Axes (from previous step)
        def get_upper_x_tick(i):
            if self.grid[1] and i in cticks[1]:
                return "┼"
            elif self.grid[1] and i in cticks[0] or i in ut.join(vticks):
                return "┬"
            elif i in cticks[1]:
                return "┴"
            else:
                return "─"

        xaxis = [get_upper_x_tick(i) for i in range(width_canvas)]
        (
            self.matrix.add_horizontal_string(
                col_start, row_end, xaxis, self.ticks_color
            )
            if self.xaxes[0] and height_canvas >= -1
            else None
        )

        # Add Left Y Ticks
        (
            [
                self.matrix.add_horizontal_string(
                    0, rticks[0][i] + row_start, ylabels[0][i], *ticks_colors
                )
                for i in range(len(rticks[0]))
            ]
            if width >= width_ylabels[0]
            else None
        )

        # Add Left Y Axis
        def get_left_y_tick(i):
            if self.grid[0] and i in rticks[0]:
                return "┼"
            elif self.grid[0] and i in rticks[1] or i in ut.join(hticks):
                return "├"
            elif i in rticks[0]:
                return "┤"
            else:
                return "│"

        yaxis = [get_left_y_tick(i) for i in range(height_canvas)]
        col_yaxis = width_ylabels[0]
        (
            self.matrix.add_vertical_string(
                col_yaxis, row_start, yaxis, self.ticks_color
            )
            if self.yaxes[0] and width >= sum(width_ylabels) + 1
            else None
        )

        # Add Right Y Axis
        def tick(i):
            return (
                    "┼"
                    if (self.grid[0] and i in rticks[1])
                    else (
                        "┤"
                        if (self.grid[0] and i in rticks[0] or i in ut.join(hticks))
                        else "├" if i in rticks[1] else "│"
                    )
                )
        yaxis = [tick(i) for i in range(height_canvas)]
        (
            self.matrix.add_vertical_string(col_end, row_start, yaxis, self.ticks_color)
            if self.yaxes[1] and width >= sum(width_ylabels) + self.yaxes[0] + 1
            else None
        )

        # Add Right Y Ticks
        (
            [
                self.matrix.add_horizontal_string(
                    col_end + 1, rticks[1][i] + row_start, ylabels[1][i], *ticks_colors
                )
                for i in range(len(rticks[1]))
            ]
            if width >= sum(width_ylabels) + 1
            else None
        )

        # Add Frame 4 Corners if necessary
        canvas_test = height_canvas >= 0 and width_canvas >= 0
        (
            self.matrix.insert_element(
                col_start - 1, row_start - 1, "└", self.ticks_color
            )
            if self.xaxes[0] and self.yaxes[0] and canvas_test
            else None
        )
        (
            self.matrix.insert_element(col_end, row_start - 1, "┘", self.ticks_color)
            if self.xaxes[0] and self.yaxes[1] and canvas_test
            else None
        )
        (
            self.matrix.insert_element(col_start - 1, row_end, "┌", self.ticks_color)
            if self.xaxes[1] and self.yaxes[0] and canvas_test
            else None
        )
        (
            self.matrix.insert_element(col_end, row_end, "┐", self.ticks_color)
            if self.xaxes[1] and self.yaxes[1] and canvas_test
            else None
        )

        # Add Lower X Axes (from previous step)
        def tick(i):
            return (
                    "┼"
                    if (self.grid[1] and i in cticks[0])
                    else (
                        "┴"
                        if (self.grid[1] and i in cticks[1] or i in ut.join(vticks))
                        else "┬" if i in cticks[0] else "─"
                    )
                )
        xaxis = [tick(i) for i in range(width_canvas)]
        (
            self.matrix.add_horizontal_string(
                col_start, row_start - 1, xaxis, self.ticks_color
            )
            if self.xaxes[0] and height_canvas >= -1
            else None
        )

        # Add Left Y Label
        (
            self.matrix.add_horizontal_string(
                0, 0, self.ylabel[0], *ticks_colors, check_space=True
            )
            if self.ylabel[0] and height > 0
            else None
        )

        # Add Right Y Label
        (
            self.matrix.add_horizontal_string(
                width - 1,
                0,
                self.ylabel[1],
                *ticks_colors,
                check_space=True,
                alignment="right",
            )
            if self.ylabel[1] and height > 0
            else None
        )

        # Add Lower X Label
        (
            self.matrix.add_horizontal_string(
                col_center,
                0,
                self.xlabel[0],
                *ticks_colors,
                alignment="center",
                check_space=True,
            )
            if self.xlabel[0] and height > 0
            else None
        )

        # Add Grid Lines
        hline = "─" * width_canvas
        [
            self.matrix.add_horizontal_string(
                0 + col_start, row + row_start, hline, self.ticks_color
            )
            for row in ut.join(rticks)
            if self.grid[0]
        ]
        vline = "│" * height_canvas
        [
            self.matrix.add_vertical_string(
                col + col_start, 0 + row_start, vline, self.ticks_color
            )
            for col in ut.join(cticks)
            if self.grid[1]
        ]
        [
            self.matrix.insert_element(col + col_start, row + row_start, "┼")
            for row in ut.join(rticks)
            for col in ut.join(cticks)
            if all(self.grid)
        ]  # deals with the crossing between grids

        # Add user defined Lines
        [
            [
                self.matrix.add_horizontal_string(
                    col_start, hticks[i][line_idx] + row_start, hline, self.hcolors[i][line_idx]
                )
                for line_idx in hline_indices[i]
            ]
            for i in r2
        ]
        [
            [
                self.matrix.add_vertical_string(
                    vticks[i][line_idx] + col_start, 0 + row_start, vline, self.vcolors[i][line_idx]
                )
                for line_idx in vline_indices[i]
            ]
            for i in r2
        ]
        [
            [
                [
                    self.matrix.insert_element(
                        col + col_start,
                        hticks[i][line_idx] + row_start,
                        "┼",
                        self.hcolors[i][line_idx],
                    )
                    for line_idx in hline_indices[i]
                ]
                for i in r2
            ]
            for col in ut.join(cticks)
            if self.grid[1]
        ]  # deals with the crossing between h lines and v grids
        [
            [
                [
                    self.matrix.insert_element(
                        vticks[i][line_idx] + col_start,
                        row + row_start,
                        "┼",
                        self.vcolors[i][line_idx],
                    )
                    for line_idx in vline_indices[i]
                ]
                for i in r2
            ]
            for row in ut.join(rticks)
            if self.grid[0]
        ]  # deals with the crossing between v lines and h grids
        [
            [
                [
                    [
                        self.matrix.insert_element(
                            col_start + vticks[iv][lv],
                            hticks[i][line_idx] + row_start,
                            "┼",
                            self.hcolors[i][line_idx],
                        )
                        for line_idx in hline_indices[i]
                    ]
                    for i in r2
                ]
                for lv in vline_indices[iv]
            ]
            for iv in r2
        ]  # deals with the crossing between h and v lines

        # Expand Canvas to accommodate HD markers
        xf = [
            max([ut.marker_factor(el, 2, 2, 2) for el in self.marker[s]], default=1)
            for s in signal_indices
        ]
        yf = [
            max([ut.marker_factor(el, 2, 3, 4) for el in self.marker[s]], default=1)
            for s in signal_indices
        ]
        width_expanded = [width_canvas * el for el in xf]
        height_expanded = [height_canvas * el for el in yf]

        # Get Relative Data to Be Plotted on Matrix
        test_canvas = [width_expanded[s] * width_expanded[s] for s in signal_indices]
        x = [
            (
                ut.get_matrix_data(self.x[s], xlim[s], width_expanded[s])
                if test_canvas[s]
                else []
            )
            for s in signal_indices
        ]
        y = [
            (
                ut.get_matrix_data(self.y[s], ylim[s], height_expanded[s])
                if test_canvas[s]
                else []
            )
            for s in signal_indices
        ]
        m, c, st = self.marker, self.color, self.style

        # Add Lines between Data Points
        x, y, m, c, st = ut.transpose(
            [
                (
                    ut.get_lines(x[s], y[s], m[s], c[s], st[s])
                    if self.lines[s]
                    else (x[s], y[s], m[s], c[s], st[s])
                )
                for s in signal_indices
            ],
            5,
        )

        # Fillx
        # x, y, m, c, st = ut.transpose([ut.brush(x[s], y[s], m[s], c[s], st[s]) for s in signal_indices], 5)
        level = [
            ut.get_fill_level(self.fillx[s], ylim[s], height_expanded[s])
            for s in signal_indices
        ]
        x, y, m, c, st = ut.transpose(
            [
                (
                    ut.fill_data(x[s], y[s], level[s], m[s], c[s], st[s])
                    if self.fillx[s] is not False
                    else (x[s], y[s], m[s], c[s], st[s])
                )
                for s in signal_indices
            ],
            5,
        )

        # Filly
        # x, y, m, c, st = ut.transpose([ut.brush(x[s], y[s], m[s], c[s], st[s]) for s in signal_indices], 5)
        level = [
            ut.get_fill_level(self.filly[s], xlim[s], width_expanded[s])
            for s in signal_indices
        ]
        y, x, m, c, st = ut.transpose(
            [
                (
                    ut.fill_data(y[s], x[s], level[s], m[s], c[s], st[s])
                    if self.filly[s] is not False
                    else (y[s], x[s], m[s], c[s], st[s])
                )
                for s in signal_indices
            ],
            5,
        )

        # Get Actual HD Markers
        x, y, m, c, st = ut.transpose(
            [ut.brush(x[s], y[s], m[s], c[s], st[s]) for s in signal_indices], 5
        )
        xf = [[ut.marker_factor(el, 2, 2, 2) for el in m[s]] for s in signal_indices]
        yf = [[ut.marker_factor(el, 2, 3, 4) for el in m[s]] for s in signal_indices]
        test = [max(xf[s], default=1) * max(yf[s], default=1) != 1 for s in signal_indices]
        x, y, mxy = ut.transpose(
            [
                ut.hd_group(x[s], y[s], xf[s], yf[s]) if test[s] else (x[s], y[s], [])
                for s in signal_indices
            ],
            3,
        )
        m = [
            [
                ut.get_hd_marker(mxy[s][i]) if m[s][i] in ut.hd_symbols else m[s][i]
                for i in range(len(x[s]))
            ]
            for s in signal_indices
        ]

        # Add Data to Canvas
        x, y, m, c, st = ut.transpose(
            [
                ut.remove_outsiders(
                    x[s], y[s], width_canvas, height_canvas, m[s], c[s], st[s]
                )
                for s in signal_indices
            ],
            5,
        )

        x, y, m, c, st = ut.transpose(
            [ut.brush(x[s], y[s], m[s], c[s], st[s]) for s in signal_indices], 5
        )
        [
            [
                self.matrix.insert_element(
                    x[s][i] + col_start, y[s][i] + row_start, m[s][i], c[s][i], st[s][i]
                )
                for i in range(len(x[s]))
            ]
            for s in signal_indices
        ]

        # Legend Utilities
        def labelled(s):
            return self.label[s] is not None
        labels = [ut.space + self.label[s] + ut.space for s in signal_indices if labelled(s)]
        label_count = len(labels)
        max_label_length = ut.max_length(labels)
        labels = [el + ut.space * (max_label_length - len(el)) for el in labels]

        # Add Legend Side Symbols
        side = [
            ut.space + ut.side_symbols[(self.xside[s], self.yside[s])]
            for s in signal_indices
            if labelled(s)
        ]
        side_test = ut.no_duplicates(side) != [" L"] and label_count != 1
        side_width = 2 if side_test else 0
        legend_test = width_canvas >= side_width + 3 + max_label_length and height_canvas >= len(labels)
        (
            [
                self.matrix.add_horizontal_string(
                    col_start,
                    row_end - 1 - s,
                    side[s],
                    self.ticks_color,
                    self.ticks_style,
                )
                for s in range(label_count)
            ]
            if legend_test and side_test
            else None
        )

        # Add Legend Markers
        def take_3(data):
            return (data[:3] * 3)[:3]
        marker = [take_3(self.marker[s]) for s in signal_indices if labelled(s)]
        def replace_hd_marker(marker):
            return (
                    ut.hd_symbols.get(marker, marker)
                )
        marker = [[ut.space] + list(map(replace_hd_marker, el)) for el in marker]
        color = [[ut.no_color] + take_3(c[s]) for s in signal_indices if labelled(s)]
        style = [[ut.no_color] + take_3(st[s]) for s in signal_indices if labelled(s)]
        (
            [
                [
                    self.matrix.insert_element(
                        col_start + side_width + i,
                        row_end - 1 - s,
                        marker[s][i],
                        color[s][i],
                        style[s][i],
                    )
                    for i in range(3)
                ]
                for s in range(label_count)
            ]
            if legend_test
            else None
        )
        (
            [
                self.matrix.add_horizontal_string(
                    col_start + side_width + 3,
                    row_end - 1 - s,
                    labels[s],
                    self.ticks_color,
                    self.ticks_style,
                )
                for s in range(label_count)
            ]
            if legend_test
            else None
        )

        # Add Text to Canvas
        [
            self.matrix.add_multiple_horizontal_strings(
                col_start + tcticks[s],
                row_start + trticks[s],
                self.text[s],
                self.tfull[s],
                self.tstyle[s],
                self.tback[s],
                self.talign[s],
                False,
                True,
            )
            for s in text_indices
            if self.torien[s] is self.default.orientation[0]
        ]
        [
            self.matrix.add_multiple_vertical_strings(
                col_start + tcticks[s],
                row_start + trticks[s],
                self.text[s],
                self.tfull[s],
                self.tstyle[s],
                self.tback[s],
                self.talign[s],
                True,
            )
            for s in text_indices
            if self.torien[s] is self.default.orientation[1]
        ]
