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

#include "paimon/fs/local/local_file_system.h"

#include <fcntl.h>

#include <cassert>
#include <cerrno>
#include <cstdio>
#include <cstring>
#include <utility>

#include "fmt/format.h"
#include "paimon/common/utils/path_util.h"

namespace paimon {

Result<bool> LocalFileSystem::Exists(const std::string& path) const {
    PAIMON_ASSIGN_OR_RAISE(std::unique_ptr<LocalFile> file, LocalFile::Create(path));
    return file->Exists();
}

Result<std::unique_ptr<InputStream>> LocalFileSystem::Open(const std::string& path) const {
    PAIMON_ASSIGN_OR_RAISE(bool is_exist, Exists(path));
    if (!is_exist) {
        return Status::NotExist(fmt::format("File '{}' not exists", path));
    }
    PAIMON_ASSIGN_OR_RAISE(std::unique_ptr<LocalFile> file, LocalFile::Create(path));
    PAIMON_ASSIGN_OR_RAISE(std::unique_ptr<LocalInputStream> in,
                           LocalInputStream::Create(std::move(file)));
    return in;
}

Result<std::unique_ptr<OutputStream>> LocalFileSystem::Create(const std::string& path,
                                                              bool overwrite) const {
    PAIMON_ASSIGN_OR_RAISE(bool is_exist, Exists(path));
    if (is_exist && !overwrite) {
        return Status::Invalid(
            fmt::format("do not allow overwrite, but the file {} already exists", path));
    }
    PAIMON_ASSIGN_OR_RAISE(std::unique_ptr<LocalFile> file, LocalFile::Create(path));
    std::unique_ptr<LocalFile> parent = file->GetParentFile();
    PAIMON_RETURN_NOT_OK(Mkdirs(parent->GetPath()));
    PAIMON_ASSIGN_OR_RAISE(std::unique_ptr<LocalOutputStream> out,
                           LocalOutputStream::Create(std::move(file)));
    return out;
}

Status LocalFileSystem::Mkdirs(const std::string& path) const {
    PAIMON_ASSIGN_OR_RAISE(std::unique_ptr<LocalFile> file, LocalFile::Create(path));
    return MkdirsInternal(std::move(file));
}

Status LocalFileSystem::MkdirsInternal(std::unique_ptr<LocalFile>&& file) const {
    // Important: The 'Exists()' check above must come before the 'IsDir()'
    // check to be safe when multiple parallel instances try to create the directory
    PAIMON_ASSIGN_OR_RAISE(bool is_exist, file->Exists());
    if (is_exist) {
        PAIMON_ASSIGN_OR_RAISE(bool is_dir, file->IsDir());
        if (is_dir) {
            return Status::OK();
        } else {
            // exists and is not a directory -> is a regular file
            return Status::IOError(
                fmt::format("file {} already exists and is not a directory", file->GetPath()));
        }
    }

    std::unique_ptr<LocalFile> parent = file->GetParentFile();
    if (!parent->IsEmpty()) {
        PAIMON_RETURN_NOT_OK(MkdirsInternal(std::move(parent)));
    }
    PAIMON_ASSIGN_OR_RAISE(bool success, file->Mkdir());
    if (!success) {
        PAIMON_ASSIGN_OR_RAISE(bool is_dir, file->IsDir());
        if (is_dir) {
            return Status::OK();
        } else {
            return Status::IOError(fmt::format("create directory '{}' failed", file->GetPath()));
        }
    }
    return Status::OK();
}

Result<FileStatus> LocalFileSystem::GetFileStatus(const std::string& path) const {
    PAIMON_ASSIGN_OR_RAISE(std::unique_ptr<LocalFile> file, LocalFile::Create(path));
    PAIMON_ASSIGN_OR_RAISE(bool is_exist, file->Exists());
    if (is_exist) {
        return file->GetFileStatus();
    } else {
        return Status::NotExist(
            fmt::format("File {} does not exist or the user running "
                        "Paimon has insufficient permissions to access it.",
                        file->GetPath()));
    }
}

Status LocalFileSystem::ListDir(const std::string& directory,
                                std::vector<BasicFileStatus>* file_status_list) const {
    PAIMON_ASSIGN_OR_RAISE(std::unique_ptr<LocalFile> file, LocalFile::Create(directory));
    PAIMON_ASSIGN_OR_RAISE(bool is_exist, file->Exists());
    if (!is_exist) {
        return Status::OK();
    }
    PAIMON_ASSIGN_OR_RAISE(bool is_file, file->IsFile());
    if (is_file) {
        return Status::IOError(
            fmt::format("file {} already exists and is not a directory", file->GetPath()));
    } else {
        std::vector<std::string> file_list;
        PAIMON_RETURN_NOT_OK(file->List(&file_list));
        file_status_list->reserve(file_status_list->size() + file_list.size());
        for (const auto& f : file_list) {
            Result<FileStatus> file_status = GetFileStatus(PathUtil::JoinPath(directory, f));
            if (!file_status.ok() && !file_status.status().IsNotExist()) {
                return file_status.status();
            } else if (file_status.ok()) {
                file_status_list->emplace_back(file_status.value().GetPath(),
                                               file_status.value().IsDir());
            }
        }
        return Status::OK();
    }
}

Status LocalFileSystem::ListFileStatus(const std::string& path,
                                       std::vector<FileStatus>* file_status_list) const {
    PAIMON_ASSIGN_OR_RAISE(std::unique_ptr<LocalFile> file, LocalFile::Create(path));
    PAIMON_ASSIGN_OR_RAISE(bool is_exist, file->Exists());
    if (!is_exist) {
        return Status::OK();
    }
    PAIMON_ASSIGN_OR_RAISE(bool is_file, file->IsFile());
    if (is_file) {
        PAIMON_ASSIGN_OR_RAISE(FileStatus file_status, file->GetFileStatus());
        file_status_list->emplace_back(std::move(file_status));
    } else {
        std::vector<std::string> file_list;
        PAIMON_RETURN_NOT_OK(file->List(&file_list));
        file_status_list->reserve(file_status_list->size() + file_list.size());
        for (const auto& f : file_list) {
            Result<FileStatus> file_status = GetFileStatus(PathUtil::JoinPath(path, f));
            if (!file_status.ok() && !file_status.status().IsNotExist()) {
                return file_status.status();
            } else if (file_status.ok()) {
                file_status_list->emplace_back(std::move(file_status).value());
            }
        }
    }
    return Status::OK();
}

Status LocalFileSystem::Delete(const std::string& path, bool recursive) const {
    PAIMON_ASSIGN_OR_RAISE(std::unique_ptr<LocalFile> file, LocalFile::Create(path));
    PAIMON_ASSIGN_OR_RAISE(bool is_file, file->IsFile());
    if (is_file) {
        return file->Delete();
    }
    return Delete(std::move(file), recursive);
}

Status LocalFileSystem::Delete(std::unique_ptr<LocalFile>&& file, bool recursive) const {
    PAIMON_ASSIGN_OR_RAISE(bool is_dir, file->IsDir());
    if (is_dir) {
        std::vector<std::unique_ptr<LocalFile>> files;
        PAIMON_RETURN_NOT_OK(file->ListFiles(&files));
        if (recursive == false && !files.empty()) {
            return Status::IOError(
                fmt::format("cannot delete {}, directory is not empty", file->GetPath()));
        }
        for (auto& child : files) {
            PAIMON_RETURN_NOT_OK(Delete(std::move(child)));
        }
    }
    // Now directory is empty
    return file->Delete();
}

Status LocalFileSystem::Rename(const std::string& src, const std::string& dst) const {
    std::string err_msg = fmt::format("rename '{}' to '{}' failed, because: ", src, dst);
    PAIMON_ASSIGN_OR_RAISE(bool is_src_exist, Exists(src));
    if (!is_src_exist) {
        return Status::NotExist(err_msg, "src file not exist");
    }
    PAIMON_ASSIGN_OR_RAISE(bool is_dst_exist, Exists(dst));
    if (is_dst_exist) {
        return Status::Invalid(err_msg, "dst file already exist");
    }
    PAIMON_ASSIGN_OR_RAISE(std::unique_ptr<LocalFile> src_file, LocalFile::Create(src));
    PAIMON_ASSIGN_OR_RAISE(bool is_file, src_file->IsFile());
    std::string new_file_name = dst;

    if (is_file && new_file_name[new_file_name.length() - 1] == '/') {
        return Status::Invalid(err_msg, "src file is not a dir");
    }
    PAIMON_ASSIGN_OR_RAISE(std::unique_ptr<LocalFile> dst_file, LocalFile::Create(dst));
    std::unique_ptr<LocalFile> parent = dst_file->GetParentFile();
    PAIMON_RETURN_NOT_OK(Mkdirs(parent->GetPath()));
    if (::rename(src_file->GetPath().c_str(), dst_file->GetPath().c_str()) != 0) {
        int32_t cur_errno = errno;
        return Status::IOError(err_msg, std::strerror(cur_errno));
    }
    return Status::OK();
}

// input stream
Result<std::unique_ptr<LocalInputStream>> LocalInputStream::Create(
    std::unique_ptr<LocalFile> file) {
    PAIMON_RETURN_NOT_OK(file->OpenFile(/*is_read_file=*/true));
    return std::unique_ptr<LocalInputStream>(new LocalInputStream(std::move(file)));
}

LocalInputStream::LocalInputStream(std::unique_ptr<LocalFile>&& file) : file_(std::move(file)) {}

Status LocalInputStream::Seek(int64_t offset, SeekOrigin origin) {
    if (origin != FS_SEEK_SET && origin != FS_SEEK_CUR && origin != FS_SEEK_END) {
        return Status::Invalid(
            "invalid SeekOrigin, only support FS_SEEK_SET, FS_SEEK_CUR, and FS_SEEK_END");
    }
    auto convert_origin = [](SeekOrigin origin) -> int32_t {
        switch (origin) {
            case FS_SEEK_SET:
                return SEEK_SET;
            case FS_SEEK_CUR:
                return SEEK_CUR;
            case FS_SEEK_END:
                return SEEK_END;
            default:
                return SEEK_SET;
        }
    };
    return file_->Seek(offset, convert_origin(origin));
}

Result<int64_t> LocalInputStream::GetPos() const {
    return file_->Tell();
}

Result<int64_t> LocalInputStream::Read(char* buffer, int64_t size) {
    PAIMON_ASSIGN_OR_RAISE(int64_t read_length, file_->Read(buffer, size));
    if (read_length != size) {
        return Status::IOError(fmt::format("file '{}' read size {} != expected {}",
                                           file_->GetPath(), read_length, size));
    }
    return read_length;
}

Result<int64_t> LocalInputStream::Read(char* buffer, int64_t size, int64_t offset) {
    PAIMON_ASSIGN_OR_RAISE(int64_t read_length, file_->Read(buffer, size, offset));
    if (read_length != size) {
        return Status::IOError(fmt::format("file '{}' read size {} != expected {}",
                                           file_->GetPath(), read_length, size));
    }
    return read_length;
}

void LocalInputStream::ReadAsync(char* buffer, int64_t size, int64_t offset,
                                 std::function<void(Status)>&& callback) {
    Result<int64_t> read_size = Read(buffer, size, offset);
    Status status = Status::OK();
    if (!read_size.ok()) {
        status = read_size.status();
    } else {
        assert(read_size.value() == size);
    }
    callback(status);
}

Result<int64_t> LocalInputStream::Length() const {
    return file_->Length();
}

Status LocalInputStream::Close() {
    return file_->Close();
}

// output stream
Result<std::unique_ptr<LocalOutputStream>> LocalOutputStream::Create(
    std::unique_ptr<LocalFile> file) {
    PAIMON_RETURN_NOT_OK(file->OpenFile(/*is_read_file=*/false));
    return std::unique_ptr<LocalOutputStream>(new LocalOutputStream(std::move(file)));
}

LocalOutputStream::LocalOutputStream(std::unique_ptr<LocalFile>&& file) : file_(std::move(file)) {}

Result<int64_t> LocalOutputStream::GetPos() const {
    return file_->Tell();
}
Result<int64_t> LocalOutputStream::Write(const char* buffer, int64_t size) {
    return file_->Write(buffer, size);
}
Status LocalOutputStream::Flush() {
    return file_->Flush();
}
Status LocalOutputStream::Close() {
    return file_->Close();
}

}  // namespace paimon
