use serde::{de, Deserializer,Deserialize};
use serde_repr::*;
use std::{
    path::{Path, PathBuf},
    fs::File,
    fmt
};
use super::{
    slide::*,
    activity::*,
    layer::*,
    shape::*
};

#[derive(Deserialize, Debug)]
pub struct SrcManifestData {
    pub data: SrcManifest,
}

impl SrcManifestData {
    pub async fn load_game_id(client: &reqwest::Client, game_id:&str) -> Self {
        let text = client
            .get(&Self::url(game_id))
            .send()
            .await
            .unwrap()
            .error_for_status()
            .unwrap()
            .text()
            .await
            .unwrap();

        serde_json::from_str(&text).unwrap()
    }

    pub fn url(game_id:&str) -> String {
        format!("https://storage.googleapis.com/ji-cloud-legacy-eu-001/games/{}/json/game.json", game_id)
    }
}
#[derive(Deserialize, Debug, Clone)]
pub struct SrcManifest {
    /// Base url of the amazon bucket
    pub base_url: String,

    pub structure: ManifestStructure,

    pub album_store: AlbumStore
}


impl SrcManifest {
    pub fn game_id(&self) -> String {
        format!("{}", self.album_store.album.key)
    }

    pub fn lang_str(&self) -> &'static str {

        let tt_lang:u32 = self.album_store.album.fields.language.unwrap_or_default();

        match tt_lang { 
            16 => "da",
            8 => "nl",
            1 | 14 | 13 | 10 | 12 => "en",
            9 => "fr",
            11 => "de",
            2 => "he",
            18 => "hu",
            19 => "it",
            7 => "pt",
            6 => "ru",
            5 => "es",
            17 => "sv",
            _ => {
                log::warn!("no lang set, picking en");
                "en"
            }
        }
    }

    pub async fn load_game_id(client: &reqwest::Client, game_id:&str) -> Self {
        let text = client
            .get(&Self::url(game_id))
            .send()
            .await
            .unwrap()
            .error_for_status()
            .unwrap()
            .text()
            .await
            .unwrap();

        serde_json::from_str(&text).unwrap()
    }

    pub fn url(game_id:&str) -> String {
        format!("https://storage.googleapis.com/ji-cloud-legacy-eu-001/games/{}/json/game.json", game_id)
    }
}

#[derive(Deserialize, Debug, Clone)]
pub struct ManifestStructure {
    #[serde(rename="musicFile")]
    pub music_file: Option<String>,

    #[serde(rename="pk")]
    pub key: PrimaryKey,

    pub settings: Option<ManifestSettings>,

    #[serde(rename="shuffleType")]
    pub shuffle_type: Option<ShuffleType>,

    pub version: usize,

    pub slides: Vec<Slide>,
}

#[derive(Deserialize, Debug, Default, Clone)]
pub struct ManifestSettings {
    #[serde(rename="quizParameters")]
    pub quiz: Option<QuizSettings>,
}

#[derive(Deserialize, Debug, Clone)]
pub struct QuizSettings {
    #[serde(rename="activityTimeLimit")]
    pub activity_time_limit: Option<f64>,

    #[serde(rename="globalLivesLimit")]
    pub global_lives_limit: Option<f64>,

    #[serde(rename="globalTimeLimit")]
    pub global_time_limit: Option<f64>,

    #[serde(rename="quizModeEnabled")]
    pub enabled: Option<bool>,
}

pub type PrimaryKey = usize;

#[repr(u8)]
#[derive(Deserialize_repr, PartialEq, Debug, Clone)]
pub enum ShuffleType {
    None = 0,
    AllSlides = 1,
    Middle = 2 // All except first and last
}

//see: https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/matrix
pub type Transform = [f64;6];

#[derive(Deserialize, Debug, Clone)]
pub struct AlbumStore {
    pub album: Album,

    #[serde(rename="pk")]
    pub key: PrimaryKey,

    pub public: Option<bool>
}

#[derive(Deserialize, Debug, Clone)]
pub struct Album {
    #[serde(rename="pk")]
    pub key: PrimaryKey,
    pub fields: AlbumFields,
}

#[derive(Deserialize, Debug, Clone)]
pub struct AlbumFields {
    pub name: Option<String>,
    pub description: Option<String>,
    pub author: Option<AlbumAuthor>,
    pub hash: Option<String>,
    pub language: Option<u32>,
}


#[derive(Deserialize, Debug, Clone)]
pub struct AlbumAuthor {
    pub first_name: Option<String>,
    pub last_name: Option<String>,
}
