// 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.

#![allow(
    rustdoc::broken_intra_doc_links,
    reason = "YARD's syntax for documentation"
)]
#![allow(rustdoc::invalid_html_tags, reason = "YARD's syntax for documentation")]
#![allow(rustdoc::bare_urls, reason = "YARD's syntax for documentation")]

use std::collections::HashMap;

use magnus::Error;
use magnus::RHash;
use magnus::RModule;
use magnus::RString;
use magnus::Ruby;
use magnus::Value;
use magnus::method;
use magnus::prelude::*;
use magnus::scan_args::get_kwargs;
use magnus::scan_args::scan_args;

use crate::capability::Capability;
use crate::io::Io;
use crate::lister::Lister;
use crate::metadata::Metadata;
use crate::operator_info::OperatorInfo;
use crate::*;

/// @yard
/// The entrypoint for operating with file services and files.
#[magnus::wrap(class = "OpenDal::Operator", free_immediately, size)]
pub struct Operator {
    // We keep a reference to an `Operator` because:
    // 1. Some builder functions exist only with the `Operator` struct.
    // 2. Some builder functions don't exist in the `BlockingOperator`, e.g., `Operator::layer`, builder methods.
    //
    // We don't support async because:
    // 1. Ractor and async is not stable.
    // 2. magnus doesn't release GVL lock during operations yet.
    // 3. Majority of use cases are still blocking.
    //
    // In practice, we will not use operator directly because of the async support.
    pub async_op: ocore::Operator,
    // The cached blocking operator coming from `Operator::blocking`.
    // Important to keep in sync after making changes to the `Operator`.
    //
    // We declare this `BlockingOperator` to state the intent of assumptions instead of
    // getting a `BlockingOperator` for an operation dynamically every time.
    pub blocking_op: ocore::blocking::Operator,
}

impl Operator {
    // Convenience helper to construct operator
    #[inline]
    pub(crate) fn from_operator(operator: ocore::Operator) -> Operator {
        let handle = RUNTIME.handle();
        let _enter = handle.enter();
        let blocking_op = ocore::blocking::Operator::new(operator.clone())
            .expect("initiate blocking operator must succeed");

        Operator {
            async_op: operator,
            blocking_op,
        }
    }
}

impl Operator {
    fn new(
        ruby: &Ruby,
        scheme: String,
        options: Option<HashMap<String, String>>,
    ) -> Result<Self, Error> {
        let options = options.unwrap_or_default();

        let op = ocore::Operator::via_iter(scheme, options)
            .map_err(|err| Error::new(ruby.exception_runtime_error(), err.to_string()))?;

        Ok(Operator::from_operator(op))
    }

    /// @yard
    /// @def read(path)
    /// Reads the whole path into string.
    /// @param path [String]
    /// @return [String]
    fn read(ruby: &Ruby, rb_self: &Self, path: String) -> Result<bytes::Bytes, Error> {
        let buffer = rb_self
            .blocking_op
            .read(&path)
            .map_err(|err| Error::new(ruby.exception_runtime_error(), err.to_string()))?;
        Ok(buffer.to_bytes())
    }

    /// @yard
    /// @def write(path, buffer)
    /// Writes string into given path.
    /// @param path [String]
    /// @param buffer [String]
    /// @return [nil]
    fn write(ruby: &Ruby, rb_self: &Self, path: String, bs: RString) -> Result<(), Error> {
        rb_self
            .blocking_op
            .write(&path, bs.to_bytes())
            .map(|_| ())
            .map_err(|err| Error::new(ruby.exception_runtime_error(), err.to_string()))
    }

    /// @yard
    /// @def read(path)
    /// Gets current path's metadata **without cache** directly.
    /// @param path
    /// @return [Metadata]
    fn stat(ruby: &Ruby, rb_self: &Self, path: String) -> Result<Metadata, Error> {
        rb_self
            .blocking_op
            .stat(&path)
            .map_err(|err| Error::new(ruby.exception_runtime_error(), err.to_string()))
            .map(Metadata::new)
    }

    /// @yard
    /// @def capability
    /// Gets capabilities of the current operator
    /// @return [Capability]
    fn capability(&self) -> Result<Capability, Error> {
        let capability = self.blocking_op.info().full_capability();
        Ok(Capability::new(capability))
    }

    /// @yard
    /// @def create_dir(path)
    /// Creates directory recursively similar as `mkdir -p`
    /// The ending path must be `/`. Otherwise, OpenDAL throws `NotADirectory` error.
    /// @param path [String]
    /// @return [nil]
    fn create_dir(ruby: &Ruby, rb_self: &Self, path: String) -> Result<(), Error> {
        rb_self
            .blocking_op
            .create_dir(&path)
            .map_err(|err| Error::new(ruby.exception_runtime_error(), err.to_string()))
    }

    /// @yard
    /// @def delete(path)
    /// Deletes given path
    /// @param path [String]
    /// @return [nil]
    fn delete(ruby: &Ruby, rb_self: &Self, path: String) -> Result<(), Error> {
        rb_self
            .blocking_op
            .delete(&path)
            .map_err(|err| Error::new(ruby.exception_runtime_error(), err.to_string()))
    }

    /// @yard
    /// @def exist?(path)
    /// Returns if this path exists
    /// @param path [String]
    /// @return [Boolean]
    fn exists(ruby: &Ruby, rb_self: &Self, path: String) -> Result<bool, Error> {
        rb_self
            .blocking_op
            .exists(&path)
            .map_err(|err| Error::new(ruby.exception_runtime_error(), err.to_string()))
    }

    /// @yard
    /// @def rename(from, to)
    /// Renames a file from `from` to `to`
    /// @param from [String] a file path
    /// @param to [String] a file path
    /// @return [nil]
    fn rename(ruby: &Ruby, rb_self: &Self, from: String, to: String) -> Result<(), Error> {
        rb_self
            .blocking_op
            .rename(&from, &to)
            .map_err(|err| Error::new(ruby.exception_runtime_error(), err.to_string()))
    }

    /// @yard
    /// @def remove_all(path)
    /// Removes the path and all nested directories and files recursively
    /// @param path [String]
    /// @return [nil]
    fn remove_all(ruby: &Ruby, rb_self: &Self, path: String) -> Result<(), Error> {
        use ocore::options::DeleteOptions;
        rb_self
            .blocking_op
            .delete_options(
                &path,
                DeleteOptions {
                    recursive: true,
                    ..Default::default()
                },
            )
            .map_err(|err| Error::new(ruby.exception_runtime_error(), err.to_string()))
    }

    /// @yard
    /// @def copy(from, to)
    /// Copies a file from `from` to `to`.
    /// @param from [String] a file path
    /// @param to [String] a file path
    /// @return [nil]
    fn copy(ruby: &Ruby, rb_self: &Self, from: String, to: String) -> Result<(), Error> {
        rb_self
            .blocking_op
            .copy(&from, &to)
            .map_err(|err| Error::new(ruby.exception_runtime_error(), err.to_string()))
    }

    /// @yard
    /// @def open(path, mode)
    /// Opens a `IO`-like reader for the given path.
    /// @param path [String] file path
    /// @param mode [String] operation mode, e.g., `r`, `w`, or `rb`.
    /// @raise [ArgumentError] invalid mode, or when the mode is not unique
    /// @return [OpenDal::IO]
    fn open(ruby: &Ruby, rb_self: &Self, args: &[Value]) -> Result<Io, Error> {
        let args = scan_args::<(String,), (Option<Value>, Option<Value>), (), (), RHash, ()>(args)?;
        let (path,) = args.required;
        let (option_mode, option_permission) = args.optional;
        let kwargs = args.keywords;

        // Ruby handles Qnil safely (will not assign to Qnil)
        let mode = option_mode.unwrap_or(ruby.str_new("r").as_value());
        let permission = option_permission.unwrap_or(ruby.qnil().as_value());

        let operator = rb_self.blocking_op.clone();
        Io::new(ruby, operator, path, mode, permission, kwargs)
    }

    /// @yard
    /// @def list(limit: nil, start_after: nil, recursive: nil)
    /// Lists the directory.
    /// @param limit [usize, nil] per-request max results
    /// @param start_after [String, nil] the specified key to start listing from.
    /// @param recursive [Boolean, nil] lists the directory recursively.
    /// @return [Lister]
    pub fn list(ruby: &Ruby, rb_self: &Self, args: &[Value]) -> Result<Lister, Error> {
        let args = scan_args::<(String,), (), (), (), _, ()>(args)?;
        let (path,) = args.required;
        let kwargs = get_kwargs::<_, (), (Option<usize>, Option<String>, Option<bool>), ()>(
            args.keywords,
            &[],
            &["limit", "start_after", "recursive"],
        )?;
        let (limit, start_after, recursive) = kwargs.optional;

        let lister = rb_self
            .blocking_op
            .lister_options(
                &path,
                ocore::options::ListOptions {
                    limit,
                    start_after,
                    recursive: recursive.unwrap_or(false),
                    ..Default::default()
                },
            )
            .map_err(|err| Error::new(ruby.exception_runtime_error(), err.to_string()))?;

        Ok(Lister::new(lister))
    }

    /// @yard
    /// @def info
    /// Gets meta information of the underlying accessor.
    /// @return [OperatorInfo]
    fn info(&self) -> Result<OperatorInfo, Error> {
        Ok(OperatorInfo(self.blocking_op.info()))
    }
}

pub fn include(ruby: &Ruby, gem_module: &RModule) -> Result<(), Error> {
    let class = gem_module.define_class("Operator", ruby.class_object())?;
    class.define_singleton_method("new", function!(Operator::new, 2))?;
    class.define_method("read", method!(Operator::read, 1))?;
    class.define_method("write", method!(Operator::write, 2))?;
    class.define_method("stat", method!(Operator::stat, 1))?;
    class.define_method("capability", method!(Operator::capability, 0))?;
    class.define_method("create_dir", method!(Operator::create_dir, 1))?;
    class.define_method("delete", method!(Operator::delete, 1))?;
    class.define_method("exist?", method!(Operator::exists, 1))?;
    class.define_method("rename", method!(Operator::rename, 2))?;
    class.define_method("remove_all", method!(Operator::remove_all, 1))?;
    class.define_method("copy", method!(Operator::copy, 2))?;
    class.define_method("open", method!(Operator::open, -1))?;
    class.define_method("list", method!(Operator::list, -1))?;
    class.define_method("info", method!(Operator::info, 0))?;

    Ok(())
}
