class FilterGroup(AbstractProcessGroup):
    def __init__(self, title, fs):
        AbstractProcessGroup.__init__(self, title, fs)

        self.setupFilterLayout()

    def setupFilterLayout(self):
        filterLayout = QVBoxLayout(self)
        filterSettLayout = QHBoxLayout()

        self.filterBandChooser = QComboBox()
        self.filterTypeChooser = QComboBox()
        filterTypeLayout = QFormLayout()

        filterTypeLayout.addWidget(QLabel('Type'))
        filterTypeLayout.addWidget(self.filterBandChooser)
        bandTypes = {
            'Low Pass': '******',
            'Band Pass': '******',
            'High Pass': '******',
            'Band Stop': 'bandstop'
        }
        [self.filterBandChooser.addItem(i, bandTypes[i]) for i in bandTypes]
        self.filterBandChooser.setCurrentText('Band Pass')
        filterTypeLayout.addWidget(self.filterTypeChooser)
        filterTypes = {'Butter': 'butter', 'Bessel': 'bessel'}
        [
            self.filterTypeChooser.addItem(i, filterTypes[i])
            for i in filterTypes
        ]

        self.lowFreqEdit = QDoubleSpinBox()
        self.lowFreqEdit.setSuffix(' Hz')
        self.lowFreqEdit.setDecimals(1)
        self.lowFreqEdit.setRange(0.1, self.fs / 2 - 0.1)
        self.highFreqEdit = QDoubleSpinBox()
        self.highFreqEdit.setSuffix(' Hz')
        self.highFreqEdit.setDecimals(1)
        self.highFreqEdit.setLocale(
            QLocale(QLocale.Polish, QLocale.EuropeanUnion))
        self.highFreqEdit.setRange(0.1, self.fs / 2 - 0.1)
        self.filterBandChooser.currentTextChanged.connect(self.setFilterBand)
        filterFreqLayout = QFormLayout()
        filterFreqLayout.addRow(QLabel('Cutoff Frequencies'))
        filterFreqLayout.addRow('Low', self.lowFreqEdit)
        filterFreqLayout.addRow('High', self.highFreqEdit)

        filterOrdLayout = QFormLayout()
        self.filterOrdEdit = QSpinBox()
        self.filterOrdEdit.setMinimum(1)
        self.filterOrdEdit.setValue(5)
        filterOrdLayout.addRow(QLabel('Order'))
        filterOrdLayout.addRow(self.filterOrdEdit)

        filterSettLayout.addLayout(filterTypeLayout)
        filterSettLayout.addSpacing(10)
        filterSettLayout.addLayout(filterFreqLayout)
        filterSettLayout.addSpacing(10)
        filterSettLayout.addLayout(filterOrdLayout)

        btn = QPushButton('Show filter response')
        btn.clicked.connect(self.showFilterResponse)

        filterLayout.addLayout(filterSettLayout)
        filterLayout.addWidget(btn, 0, Qt.AlignRight)

    def setFilterBand(self):
        if self.filterBandChooser.currentText() == 'Low Pass':
            self.lowFreqEdit.setDisabled(True)
        else:
            self.lowFreqEdit.setEnabled(True)
        if self.filterBandChooser.currentText() == 'High Pass':
            self.highFreqEdit.setDisabled(True)
        else:
            self.highFreqEdit.setEnabled(True)

    def calcFilter(self):
        bandArr = [
            x.value() for x in (self.lowFreqEdit, self.highFreqEdit)
            if x.isEnabled() == True
        ]
        return filterCalc(order=self.filterOrdEdit.value(),
                          bandarr=bandArr,
                          fs=self.fs,
                          btype=self.filterBandChooser.currentData(),
                          ftype=self.filterTypeChooser.currentData())

    def showFilterResponse(self):
        bandArr = [
            x.value() for x in (self.lowFreqEdit, self.highFreqEdit)
            if x.isEnabled() == True
        ]
        b, a = self.calcFilter()
        w, h = signal.freqz(b, a)
        fig = plt.figure()
        ax1 = fig.add_subplot(111)
        ax1.set_title(
            label='Filter frequency response\n{}, {}, {}Hz, ord={}'.format(
                self.filterBandChooser.currentText(),
                self.filterTypeChooser.currentText(), bandArr,
                self.filterOrdEdit.value()))
        ax1.plot(w * (self.fs / (2 * np.pi)), 20 * np.log10(abs(h)), 'b')
        ax1.set_ylabel('Amplitude [dB]', color='b')
        ax1.set_xlabel('Frequency [Hz]')
        ax1.tick_params(axis='y', colors='b')
        ax2 = ax1.twinx()
        angles = np.unwrap(np.angle(h))
        ax2.plot(w * (self.fs / (2 * np.pi)), angles, 'g')
        ax2.set_ylabel('Angle (radians)', color='g')
        ax2.tick_params(axis='y', colors='g')
        plt.grid()
        plt.axis('tight')
        plt.show()

    def process(self, inData):
        b, a = self.calcFilter()
        outData = []
        progStep = 100.0 / len(inData)
        prog = 0
        for data in inData:
            newData = signal.lfilter(b, a, data)
            outData.append(newData)
            prog = prog + progStep
            self.progress.emit(int(prog))
        return outData