// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

use std::collections::HashMap;
use std::sync::LazyLock;

use ::opendal as od;
use ext_php_rs::binary::Binary;
use ext_php_rs::convert::FromZval;
use ext_php_rs::exception::PhpException;
use ext_php_rs::flags::DataType;
use ext_php_rs::prelude::*;
use ext_php_rs::types::Zval;

static RUNTIME: LazyLock<tokio::runtime::Runtime> = LazyLock::new(|| {
    tokio::runtime::Builder::new_multi_thread()
        .enable_all()
        .build()
        .unwrap()
});

#[php_class(name = "OpenDAL\\Operator")]
pub struct Operator(od::blocking::Operator);

#[php_impl(rename_methods = "none")]
impl Operator {
    pub fn __construct(scheme: String, config: HashMap<String, String>) -> PhpResult<Self> {
        let op = od::Operator::via_iter(scheme, config).map_err(format_php_err)?;

        let handle = RUNTIME.handle();
        let _enter = handle.enter();
        let op = od::blocking::Operator::new(op).map_err(format_php_err)?;

        Ok(Operator(op))
    }

    /// Write string into given path.
    pub fn write(&self, path: &str, content: String) -> PhpResult<()> {
        self.0
            .write(path, content)
            .map(|_| ())
            .map_err(format_php_err)
    }

    /// Write bytes into given path, binary safe.
    pub fn write_binary(&self, path: &str, content: Vec<u8>) -> PhpResult<()> {
        self.0
            .write(path, content)
            .map(|_| ())
            .map_err(format_php_err)
    }

    /// Read the whole path into bytes, binary safe.
    pub fn read(&self, path: &str) -> PhpResult<Binary<u8>> {
        self.0
            .read(path)
            .map_err(format_php_err)
            .map(|buf| Binary::from(buf.to_vec()))
    }

    /// Check if this path exists or not, return 1 if exists, 0 otherwise.
    pub fn is_exist(&self, path: &str) -> PhpResult<u8> {
        self.0
            .exists(path)
            .map_err(format_php_err)
            .map(|b| if b { 1 } else { 0 })
    }

    /// Get current path's metadata **without cache** directly.
    ///
    /// # Notes
    ///
    /// Use `stat` if you:
    ///
    /// - Want detect the outside changes of path.
    /// - Don't want to read from cached metadata.
    pub fn stat(&self, path: &str) -> PhpResult<Metadata> {
        self.0.stat(path).map_err(format_php_err).map(Metadata)
    }

    /// Delete given path.
    ///
    /// # Notes
    ///
    /// - Delete not existing error won't return errors.
    pub fn delete(&self, path: &str) -> PhpResult<()> {
        self.0.delete(path).map_err(format_php_err)
    }

    /// Create a dir at given path.
    ///
    /// # Notes
    ///
    /// To indicate that a path is a directory, it is compulsory to include
    /// a trailing / in the path. Failure to do so may result in
    /// `NotADirectory` error being returned by OpenDAL.
    ///
    /// # Behavior
    ///
    /// - Create on existing dir will succeed.
    /// - Create dir is always recursive, works like `mkdir -p`
    pub fn create_dir(&self, path: &str) -> PhpResult<()> {
        self.0.create_dir(path).map_err(format_php_err)
    }
}

#[php_class(name = "OpenDAL\\Metadata")]
pub struct Metadata(od::Metadata);

#[php_impl(rename_methods = "none")]
impl Metadata {
    #[getter]
    pub fn content_disposition(&self) -> Option<String> {
        self.0.content_disposition().map(|s| s.to_string())
    }

    /// Content length of this entry.
    #[getter]
    pub fn content_length(&self) -> u64 {
        self.0.content_length()
    }

    /// Content MD5 of this entry.
    #[getter]
    pub fn content_md5(&self) -> Option<String> {
        self.0.content_md5().map(|s| s.to_string())
    }

    /// Content Type of this entry.
    #[getter]
    pub fn content_type(&self) -> Option<String> {
        self.0.content_type().map(|s| s.to_string())
    }

    /// ETag of this entry.
    #[getter]
    pub fn etag(&self) -> Option<String> {
        self.0.etag().map(|s| s.to_string())
    }

    /// mode represent this entry's mode.
    #[getter]
    pub fn mode(&self) -> EntryMode {
        EntryMode(self.0.mode())
    }
}

#[php_class(name = "OpenDAL\\EntryMode")]
pub struct EntryMode(od::EntryMode);

impl<'b> FromZval<'b> for EntryMode {
    const TYPE: DataType = DataType::Object(Some("OpenDAL\\EntryMode"));

    fn from_zval(zval: &'b Zval) -> Option<Self> {
        zval.object().and_then(|obj| obj.get_property("mode").ok())
    }
}

#[php_impl(rename_methods = "none")]
impl EntryMode {
    #[getter]
    pub fn is_dir(&self) -> u8 {
        match self.0.is_dir() {
            true => 1,
            false => 0,
        }
    }

    #[getter]
    pub fn is_file(&self) -> u8 {
        match self.0.is_file() {
            true => 1,
            false => 0,
        }
    }
}

fn format_php_err(e: od::Error) -> PhpException {
    // @todo use custom exception, we cannot use custom exception now,
    // see https://github.com/davidcole1340/ext-php-rs/issues/262
    PhpException::default(e.to_string())
}

#[php_module]
pub fn get_module(module: ModuleBuilder) -> ModuleBuilder {
    module
}
