#![allow(unused)]
use actix::{Actor, StreamHandler};
use actix_files::{Files, NamedFile};
use actix_form_data::{Error, Field, Value};
use actix_identity::Identity;
use actix_identity::{CookieIdentityPolicy, IdentityService};
use actix_multipart::Multipart;
use actix_web::{
    cookie::Cookie, get, http, middleware, post, web, web::Data, web::Form, web::Path as Pathweb,
    App, HttpRequest, HttpResponse, HttpServer, Responder,
};
use actix_web_actors::ws;

use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::{fs::*, default};
use std::path::*;
use std::process::Command;
use tera::{Context, Tera};

#[macro_use]
extern crate diesel;
use diesel::prelude::*;

pub mod schema;
use schema::users;
pub mod models;
use models::{User};

use walkdir::{DirEntry, WalkDir};

mod user_controller;

mod response;
mod util;
use util::*;
// use response::MyError;

use futures_util::TryStreamExt as _;
use std::io::Write;
use tempfile::tempfile;
use uuid::Uuid;

use std::fs::File;
use std::io::{self, prelude::*, BufReader};


#[get("/")]
async fn index(tmpl: Data<Tera>, id: Identity) -> impl Responder {
    let mut context = Context::new();
    let result_user = get_user_session(&id);
    if !result_user.is_err() {
        let user_session = result_user.unwrap();
        context.insert("user", &user_session);
    }
    response::template(tmpl, "index.html.twig", &context)
}


#[derive(Debug, Deserialize)]
pub struct ParamsMedias {
    q: String,
}

#[get("/medias")]
async fn medias(req: HttpRequest, tmpl: Data<Tera>, id: Identity) -> impl Responder {
    let mut context = Context::new();
    let result_user = get_user_session(&id);
    if !result_user.is_err() {
        let user_session = result_user.unwrap();
        context.insert("user", &user_session);
    }
    let params_result = web::Query::<ParamsMedias>::from_query(req.query_string());
    if params_result.is_err() {
        return response::redirect("/");
    }
    let params = params_result.unwrap();
    context.insert("path", &params.q);
    response::template(tmpl, "medias.html.twig", &context)
}

async fn not_found(req: HttpRequest, tmpl: Data<Tera>, id: Identity) -> impl Responder {
    let context = Context::new();
    response::just_404(tmpl)
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        let tera = Tera::new(concat!(env!("CARGO_MANIFEST_DIR"), "/templates/**/*")).unwrap();
        let mut folder_static = "static/";
        App::new()
            .app_data(Data::new(tera))
            .wrap(IdentityService::new(
                CookieIdentityPolicy::new(&[0; 32])
                    .name("dr_who_website")
                    .secure(true)
                    .max_age_secs(60 * 60 * 24 * 7), // 1week
            ))
            .wrap(middleware::Logger::default())
            .service(index)
            .service(medias)
            .service(user_controller::login)
            .service(user_controller::post_login)
            .service(user_controller::post_auth)
            .service(user_controller::post_auth_user)
            .service(user_controller::register)
            .service(user_controller::post_register)
            .service(user_controller::logout)
            .service(user_controller::register_google)
            .service(user_controller::post_register_google)
            .service(user_controller::user_validate)
            .service(user_controller::forgotpassword)
            .service(user_controller::post_forgotpassword)
            .service(user_controller::change_password)
            .service(user_controller::post_change_password)
            .service(user_controller::profile)
            .service(user_controller::profile_post)
            .service(user_controller::delete)
            .service(user_controller::user_deleted)
            .service(Files::new("/static", folder_static))
            .default_service(web::route().to(not_found))
    })
    .workers(8)
    .bind(("0.0.0.0", 80))?
    .run()
    .await
}