//! Pattern and step editing operations (toggle, length, speed, delete, reset).

use crate::services::pattern_editor;
use crate::state::FlashKind;

use super::App;

impl App {
    pub fn toggle_steps(&mut self) {
        let (bank, pattern) = self.current_bank_pattern();
        for idx in self.selected_steps() {
            pattern_editor::toggle_step(&mut self.project_state.project, bank, pattern, idx);
        }
        self.project_state.mark_dirty(bank, pattern);
    }

    pub fn length_increase(&mut self) {
        let (bank, pattern) = self.current_bank_pattern();
        let (change, _) =
            pattern_editor::increase_length(&mut self.project_state.project, bank, pattern);
        self.project_state.mark_dirty(change.bank, change.pattern);
    }

    pub fn length_decrease(&mut self) {
        let (bank, pattern) = self.current_bank_pattern();
        let (change, new_len) =
            pattern_editor::decrease_length(&mut self.project_state.project, bank, pattern);
        if self.editor_ctx.step >= new_len {
            self.editor_ctx.step = new_len - 1;
            self.load_step_to_editor();
        }
        self.project_state.mark_dirty(change.bank, change.pattern);
    }

    pub fn speed_increase(&mut self) {
        let (bank, pattern) = self.current_bank_pattern();
        let change = pattern_editor::increase_speed(&mut self.project_state.project, bank, pattern);
        self.project_state.mark_dirty(change.bank, change.pattern);
    }

    pub fn speed_decrease(&mut self) {
        let (bank, pattern) = self.current_bank_pattern();
        let change = pattern_editor::decrease_speed(&mut self.project_state.project, bank, pattern);
        self.project_state.mark_dirty(change.bank, change.pattern);
    }

    pub fn delete_step(&mut self, bank: usize, pattern: usize, step: usize) {
        let edit = pattern_editor::delete_step(&mut self.project_state.project, bank, pattern, step);
        self.project_state.mark_dirty(edit.bank, edit.pattern);
        if self.editor_ctx.bank == bank
            && self.editor_ctx.pattern == pattern
            && self.editor_ctx.step == step
        {
            self.load_step_to_editor();
        }
        self.ui.flash("Step deleted", 150, FlashKind::Success);
    }

    pub fn delete_steps(&mut self, bank: usize, pattern: usize, steps: &[usize]) {
        let edit = pattern_editor::delete_steps(&mut self.project_state.project, bank, pattern, steps);
        self.project_state.mark_dirty(edit.bank, edit.pattern);
        if self.editor_ctx.bank == bank && self.editor_ctx.pattern == pattern {
            self.load_step_to_editor();
        }
        self.editor_ctx.clear_selection();
        self.ui.flash(
            &format!("{} steps deleted", steps.len()),
            150,
            FlashKind::Success,
        );
    }

    pub fn reset_pattern(&mut self, bank: usize, pattern: usize) {
        let edit = pattern_editor::reset_pattern(&mut self.project_state.project, bank, pattern);
        self.project_state.mark_dirty(edit.bank, edit.pattern);
        if self.editor_ctx.bank == bank && self.editor_ctx.pattern == pattern {
            self.load_step_to_editor();
        }
        self.ui.flash("Pattern reset", 150, FlashKind::Success);
    }

    pub fn reset_bank(&mut self, bank: usize) {
        let pat_count = pattern_editor::reset_bank(&mut self.project_state.project, bank);
        for pattern in 0..pat_count {
            self.project_state.mark_dirty(bank, pattern);
        }
        if self.editor_ctx.bank == bank {
            self.load_step_to_editor();
        }
        self.ui.flash("Bank reset", 150, FlashKind::Success);
    }

    pub fn reset_patterns(&mut self, bank: usize, patterns: &[usize]) {
        for &pattern in patterns {
            let edit =
                pattern_editor::reset_pattern(&mut self.project_state.project, bank, pattern);
            self.project_state.mark_dirty(edit.bank, edit.pattern);
        }
        if self.editor_ctx.bank == bank && patterns.contains(&self.editor_ctx.pattern) {
            self.load_step_to_editor();
        }
        let n = patterns.len();
        self.ui.flash(
            &format!("{n} pattern{} reset", if n == 1 { "" } else { "s" }),
            150,
            FlashKind::Success,
        );
    }

    pub fn reset_banks(&mut self, banks: &[usize]) {
        for &bank in banks {
            let pat_count =
                pattern_editor::reset_bank(&mut self.project_state.project, bank);
            for pattern in 0..pat_count {
                self.project_state.mark_dirty(bank, pattern);
            }
        }
        if banks.contains(&self.editor_ctx.bank) {
            self.load_step_to_editor();
        }
        let n = banks.len();
        self.ui.flash(
            &format!("{n} bank{} reset", if n == 1 { "" } else { "s" }),
            150,
            FlashKind::Success,
        );
    }
}
