/*
 * 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.
 */
#pragma once

#include <Formats/FormatSettings.h>
#include <IO/ReadBuffer.h>
#include <IO/ReadHelpers.h>


#include <Common/LocalDate.h>
#include <Common/StringUtils.h>

#include "ExcelNumberReader.h"

namespace local_engine
{

inline bool checkDate(const UInt16 & year, const UInt8 & month_, const UInt8 & day_)
{
    auto is_leap_year_ = (year % 400 == 0) || (year % 100 != 0 && year % 4 == 0);

    if ((month_ == 1 || month_ == 3 || month_ == 5 || month_ == 7 || month_ == 8 || month_ == 10 || month_ == 12) && day_ >= 1
        && day_ <= 31)
        return true;
    else if (month_ == 2 && ((is_leap_year_ && day_ >= 1 && day_ <= 29) || (!is_leap_year_ && day_ >= 1 && day_ <= 28)))
        return true;
    else if ((month_ == 4 || month_ == 6 || month_ == 9 || month_ == 11) && day_ >= 1 && day_ <= 30)
        return true;
    return false;
}

inline size_t readDigits(char * res, size_t max_chars, DB::ReadBuffer & in)
{
    size_t num_chars = 0;
    while (!in.eof() && isNumericASCII(*in.position()) && num_chars < max_chars)
    {
        res[num_chars] = *in.position() - '0';
        ++num_chars;
        ++in.position();
    }
    return num_chars;
}

template <size_t digit, size_t power_of_ten, typename T>
inline void readDecimalNumberImpl(T & res, const char * src)
{
    res += src[digit] * power_of_ten;
    if constexpr (digit > 0)
        readDecimalNumberImpl<digit - 1, power_of_ten * 10>(res, src);
}

template <size_t num_digits, typename T>
inline void readDecimalNumber(T & res, const char * src)
{
    readDecimalNumberImpl<num_digits - 1, 1>(res, src);
}

template <size_t num_digits, typename T>
inline bool readNumber(DB::ReadBuffer & buf, T & res)
{
    char digits[std::numeric_limits<UInt64>::digits10];
    size_t read_num_digits = readDigits(digits, sizeof(digits), buf);

    if (read_num_digits != num_digits)
        return false;

    readDecimalNumber<num_digits>(res, digits);
    return true;
}


bool readDatetime64TextWithExcel(
    DB::DateTime64 & datetime64,
    UInt32 scale,
    DB::ReadBuffer & buf,
    const DateLUTImpl & time_zone,
    const DB::FormatSettings::CSV & settings,
    bool quote);
bool readDateTime64Text(
    DB::DateTime64 & x,
    DB::ReadBuffer & buf,
    const DB::FormatSettings & settings,
    const DateLUTImpl & time_zone,
    const DateLUTImpl & utc_time_zone,
    bool quote);

bool readDateTextWithExcel(LocalDate & date, DB::ReadBuffer & buf, bool is_us_style, const DB::FormatSettings & settings);
bool readDateText(LocalDate & date, DB::ReadBuffer & buf, const DB::FormatSettings & settings);


template <typename T>
inline bool readExcelIntegerText(T & x, DB::ReadBuffer & buf, bool has_quote, const DB::FormatSettings & settings)
{
    if constexpr (std::is_same_v<decltype(x), bool &>)
    {
        readBoolText(x, buf);
        return true;
    }
    else
        return readExcelIntTextImpl(x, buf, has_quote, settings);
}

inline bool readExcelText(is_floating_point auto & x, DB::ReadBuffer & buf, bool has_quote, const DB::FormatSettings & settings)
{
    return readExcelFloatTextFastImpl(x, buf, has_quote, settings);
}

inline bool readExcelText(is_integer auto & x, DB::ReadBuffer & buf, bool has_quote, const DB::FormatSettings & settings)
{
    return readExcelIntegerText(x, buf, has_quote, settings);
}

inline bool readExcelText(LocalDate & x, DB::ReadBuffer & buf, bool /*has_quote*/, const DB::FormatSettings & settings)
{
    return readDateText(x, buf, settings);
}

/// CSV, for numbers, dates: quotes are optional, no special escaping rules.
template <typename T>
bool readCSVSimple(T & x, DB::ReadBuffer & buf, const DB::FormatSettings & settings)
{
    if (buf.eof())
        DB::throwReadAfterEOF();

    char maybe_quote = *buf.position();
    bool has_quote = false;
    if ((settings.csv.allow_single_quotes && maybe_quote == '\'') || (settings.csv.allow_double_quotes && maybe_quote == '\"'))
    {
        has_quote = true;
        ++buf.position();
    }

    /// deal empty string ""
    if ((has_quote && !buf.eof() && *buf.position() == maybe_quote)
        || (!has_quote && !buf.eof() && (*buf.position() == settings.csv.delimiter || *buf.position() == '\n' || *buf.position() == '\r')))
        return false;

    bool result = readExcelText(x, buf, has_quote, settings);
    if (!result)
        return false;

    if (has_quote)
        assertChar(maybe_quote, buf);

    while (!buf.eof() && *buf.position() == ' ')
    {
        //ignore end whitespace
        ++buf.position();
    }


    if (!buf.eof() && (*buf.position() != settings.csv.delimiter && *buf.position() != '\n' && *buf.position() != '\r'))
        return false;

    return true;
}


template <typename T>
requires is_arithmetic_v<T>
inline bool readCSV(T & x, DB::ReadBuffer & buf, const DB::FormatSettings & settings)
{
    return readCSVSimple(x, buf, settings);
}

inline bool readCSV(LocalDate & x, DB::ReadBuffer & buf, const DB::FormatSettings & settings)
{
    return readCSVSimple(x, buf, settings);
}

}
