from core.data_buffer import DataBuffer


class MultiChannel:
    def __init__(self, steps, bases, roofs):
        self.steps = steps
        self.bases = bases
        self.roofs = roofs
        self.cur_channel = self.bases[0]
        self.cur_roof = self.roofs[0]
        self.cur_step = self.steps[0]
        self.num_chs = []
        self.init_freq = False
        self.DB = []

    def init_f(self):
        self.init_freq = True
        return self.bases[0]

    def get_cur_channel(self):
        return self.cur_channel

    @staticmethod
    def _range_finished(channel, roof, step):
        if step < 0:
            return channel <= roof
        return channel >= roof

    def change_channel(self):
        if not self.init_freq:
            return self.init_f()

        current_idx = self.roofs.index(self.cur_roof)
        if self._range_finished(self.cur_channel, self.cur_roof, self.cur_step):
            next_idx = (current_idx + 1) % len(self.bases)
            self.cur_channel = self.bases[next_idx]
            self.cur_roof = self.roofs[next_idx]
            self.cur_step = self.steps[next_idx]
        else:
            self.cur_channel += self.cur_step
        return self.get_cur_channel()

    def get_num_chs(self, idx_freq):
        if (idx_freq + 1) > len(self.num_chs):
            tmp = self.bases[idx_freq]
            roof = self.roofs[idx_freq]
            step = self.steps[idx_freq]
            counter = 0
            if step == 0:
                raise ValueError('step must not be zero')
            if step < 0:
                while tmp >= roof:
                    counter += 1
                    tmp += step
            else:
                while tmp <= roof:
                    counter += 1
                    tmp += step
            self.num_chs.append(counter)
            return counter
        return self.num_chs[idx_freq]

    def check_f(self, freq):
        for i in range(len(self.bases)):
            low = min(self.roofs[i], self.bases[i])
            high = max(self.roofs[i], self.bases[i])
            if low <= freq <= high:
                return self.get_num_chs(i), self.DB[i]
        return None, None

    def fill_DB(self, buffer_columns_size, num_of_thinning_iter, multiply_factor, num_for_alarm, freq_tag=None):
        self.DB = []
        for i in range(len(self.bases)):
            num_chs = self.get_num_chs(i)
            self.DB.append(
                DataBuffer(
                    buffer_columns_size,
                    num_of_thinning_iter,
                    num_chs,
                    multiply_factor,
                    num_for_alarm,
                    freq_tag=freq_tag,
                )
            )

    def db_alarms_zeros(self, circle_buffer):
        for i in range(len(self.DB)):
            if self.DB[i] != circle_buffer:
                self.DB[i].alarms_fill_zeros()
