use std::sync::Arc;

use axum::{
    Router,
    routing::{delete, get, post},
};
use tokio::sync::Semaphore;

use crate::{config::Config, diagnostics, media, media::dash::DashManager, web};

pub struct AppState {
    pub config: Config,
    pub dash: DashManager,
    pub preview_jobs: Semaphore,
}

impl AppState {
    pub fn new(config: Config) -> anyhow::Result<Self> {
        Ok(Self {
            config,
            dash: DashManager::new()?,
            preview_jobs: Semaphore::new(2),
        })
    }
}

pub fn router(state: Arc<AppState>) -> Router {
    Router::new()
        .route("/", get(web::index))
        .route("/alpine.min.js", get(web::alpine))
        .route("/dash.all.min.js", get(web::dash))
        .route("/dash.all.min.js.map", get(web::dash_source_map))
        .route("/controlbar.min.js", get(web::controlbar_javascript))
        .route("/controlbar.css", get(web::controlbar_styles))
        .route("/bootstrap-icons.min.css", get(web::bootstrap_icon_styles))
        .route(
            "/fonts/bootstrap-icons.woff2",
            get(web::bootstrap_icon_font),
        )
        .route("/js/api.js", get(web::api_javascript))
        .route("/js/library.js", get(web::library_javascript))
        .route("/js/location.js", get(web::location_javascript))
        .route("/js/preferences.js", get(web::preferences_javascript))
        .route("/js/player.js", get(web::player_javascript))
        .route("/styles.css", get(web::styles))
        .route("/api/info", get(diagnostics::info))
        .route("/api/browse", get(media::browse::browse))
        .route("/api/probe", get(media::probe::probe))
        .route("/api/preview", get(media::preview::sprite))
        .route("/api/stream", get(media::stream::stream))
        .route("/api/subtitles", get(media::subtitles::list))
        .route("/api/subtitles/{index}", get(media::subtitles::extract))
        .route(
            "/api/subtitles/external/{id}",
            get(media::subtitles::extract_external),
        )
        .route("/api/dash", post(media::dash::start))
        .route("/api/dash/{session}", delete(media::dash::stop))
        .route("/api/dash/{session}/{asset}", get(media::dash::asset))
        .with_state(state)
}
