use crate::RootMessage;
use crate::dictionary::split_with_coma;
use crate::dictionary_test::DictionaryQuizMessage::*;
use crate::lang::WordData;
use crate::navigation::Page::PreviousPage;
use crate::navigation::*;
use crate::quiz::Score;
use crate::styling::*;
use iced::Background::Color;
use iced::border::Radius;
use iced::widget::container::Style;
use iced::widget::{Row, button, container, row, space, text, text_input};
use iced::{Border, Element, Fill, Task, Theme, alignment};
use rand::prelude::SliceRandom;

#[derive(Debug, Clone)]
pub struct DictionaryQuizState {
    words: Vec<WordData>,
    current_set: Vec<WordData>,
    answer: String,
    view: String,
    correct: String,
    score: Score,
    is_help: bool,
    reverse: bool,
    laps: u32,
    no_typing: bool,
}
#[derive(Debug, Clone)]
pub enum DictionaryQuizMessage {
    Back,
    AnswerChanged(String),
    SubmitAnswer,
    Appeal,
}

impl NavigatedPage<DictionaryQuizMessage> for DictionaryQuizState {
    fn navigate(&mut self, message: &DictionaryQuizMessage) -> Option<Page> {
        match message {
            Back => Some(PreviousPage),
            _ => None,
        }
    }

    fn navigated(&mut self) {}

    fn update(&mut self, message: DictionaryQuizMessage) -> Task<RootMessage> {
        match message {
            Back => {}
            AnswerChanged(c) => self.answer = c.clone(),
            SubmitAnswer => self.submit(),
            Appeal => self.appeal_answer(),
        }
        Task::none()
    }

    fn view(&self) -> Element<'_, DictionaryQuizMessage> {
        container(
            iced::widget::column![
                self.laps(),
                iced::widget::column![
                    text!("{}", self.view).size(54),
                    text!(
                        "{}",
                        if self.is_help {
                            self.correct.clone()
                        } else {
                            String::new()
                        }
                    )
                    .size(ACCENT_FONT_SIZE)
                    .align_y(alignment::Vertical::Center),
                ]
                .align_x(alignment::Horizontal::Center)
                .spacing(5),
                text_input("Перевод", &self.answer)
                    .size(28)
                    .width(250)
                    .on_input(AnswerChanged)
                    .on_submit(SubmitAnswer),
                row![
                    text!("{}", self.score.total.to_string()).size(25),
                    text!("{}", self.score.correct.to_string())
                        .size(25)
                        .color(iced::Color::from_rgb8(60, 170, 60)),
                    text!("{}", self.score.fail.to_string())
                        .color(iced::Color::from_rgb8(255, 79, 0))
                        .size(25),
                ]
                .spacing(DEFAULT_SPACING),
                row![
                    button("Закончить").style(jl_button).on_press(Back),
                    self.appeal_button()
                ]
                .spacing(DEFAULT_SPACING),
            ]
            .spacing(DEFAULT_SPACING)
            .align_x(alignment::Horizontal::Center),
        )
        .center_y(Fill)
        .center_x(Fill)
        .into()
    }
}

impl DictionaryQuizState {
    pub fn new(words: Vec<WordData>, reverse: bool, no_typing: bool) -> DictionaryQuizState {
        DictionaryQuizState {
            words,
            current_set: Vec::new(),
            answer: "".to_string(),
            view: "---".to_string(),
            correct: "".to_string(),
            score: Default::default(),
            is_help: false,
            reverse,
            laps: 0,
            no_typing,
        }
    }

    fn submit(&mut self) {
        if self.view == "---" {
            self.show_next();
            return;
        }

        if self.no_typing {
            self.no_type_submit();
        } else {
            self.default_submit();
        }
    }

    fn no_type_submit(&mut self) {
        if self.is_help {
            self.is_help = false;
            self.score.total += 1;
            self.show_next()
        } else {
            self.is_help = true;
        }
    }

    fn default_submit(&mut self) {
        if !self.is_help {
            self.score.total += 1;
        }
        if self.answer == self.correct
            || split_with_coma(self.correct.as_str()).contains(&self.answer)
        {
            if !self.is_help {
                self.score.correct += 1;
            }
            self.show_next()
        } else {
            self.score.fail += 1;
            self.is_help = true;
        }
    }

    fn update_set(&mut self) {
        self.current_set.append(&mut self.words.clone());
        self.current_set.shuffle(&mut rand::rng());
        if self.score.total != 0 {
            self.laps += 1;
        }
    }

    fn show_next(&mut self) {
        self.is_help = false;
        self.answer = String::new();

        let next: WordData = match self.current_set.pop() {
            Some(word) => word,
            None => {
                self.update_set();
                self.current_set.pop().expect("Empty set")
            }
        };

        if self.reverse {
            self.view = next.value.clone();
            self.correct = next.key.clone();
        } else {
            self.view = next.key.clone();
            self.correct = next.value.clone();
        }
    }

    fn laps(&self) -> Element<'_, DictionaryQuizMessage> {
        let mut col = Row::new();
        for _ in 0..self.laps {
            col = col.push(iced::widget::container(space().height(15).width(15)).style(
                |x: &Theme| Style {
                    text_color: None,
                    background: Some(Color(x.palette().primary)),
                    border: Border {
                        color: Default::default(),
                        width: 0.0,
                        radius: Radius::new(5),
                    },
                    shadow: Default::default(),
                    snap: false,
                },
            ));
        }
        col.spacing(DEFAULT_SPACING).into()
    }

    fn appeal_button(&self) -> Element<'_, DictionaryQuizMessage> {
        if self.is_help && !self.no_typing {
            return button("Апелляция").style(jl_button).on_press(Appeal).into();
        }
        space().into()
    }

    fn appeal_answer(&mut self) {
        self.score.correct += 1;
        self.score.fail -= 1;
        self.answer = self.correct.clone();
        self.show_next()
    }
}
