//--------------------------------------------------------------------------------------------------
// Copyright (c) id3 Technologies
// All Rights Reserved.
//--------------------------------------------------------------------------------------------------
#pragma once
#include <id3BiosealCppWrapper/id3BiosealException.hpp>
#include <id3Bioseal/id3BiosealDateTime.h>

namespace id3BiosealCppWrapper
{

/**
 * Represents a date/time.
 */
class DateTime
{
private:
    ID3_BIOSEAL_DATE_TIME handle_{};

public:
    DateTime() {
        check_error(id3BiosealDateTime_Initialize(&handle_));
    }

    virtual ~DateTime() {
        if (handle_) {
            id3BiosealDateTime_Dispose(&handle_);
        }
    }


    DateTime(DateTime &&src) noexcept: handle_(src.handle_) {
        src.handle_ = nullptr;
    }

    ID3_BIOSEAL_DATE_TIME getHandle() const { return handle_; }
    operator ID3_BIOSEAL_DATE_TIME () const { return handle_; }

    // public getters and setters
    /**
    * Gets the the year (1 through 9999, 0 if invalid date).
    * @exception BiosealException An error has occured during Bioseal library execution.
    * @retval The year (1 through 9999, 0 if invalid date).
    */
    int getYear() {
        int year;
        check_error(id3BiosealDateTime_GetYear(handle_, &year));
        return year;
    }

    /**
    * Gets the the month (1 through 12).
    * @exception BiosealException An error has occured during Bioseal library execution.
    * @retval The month (1 through 12).
    */
    int getMonth() {
        int month;
        check_error(id3BiosealDateTime_GetMonth(handle_, &month));
        return month;
    }

    /**
    * Gets the the day (1 through the number of days in month).
    * @exception BiosealException An error has occured during Bioseal library execution.
    * @retval The day (1 through the number of days in month).
    */
    int getDay() {
        int day;
        check_error(id3BiosealDateTime_GetDay(handle_, &day));
        return day;
    }

    /**
    * Gets the the hour (0 through 23, -1 if invalid time).
    * @exception BiosealException An error has occured during Bioseal library execution.
    * @retval The hour (0 through 23, -1 if invalid time).
    */
    int getHour() {
        int hour;
        check_error(id3BiosealDateTime_GetHour(handle_, &hour));
        return hour;
    }

    /**
    * Gets the the minute (0 through 59).
    * @exception BiosealException An error has occured during Bioseal library execution.
    * @retval The minute (0 through 59).
    */
    int getMinute() {
        int minute;
        check_error(id3BiosealDateTime_GetMinute(handle_, &minute));
        return minute;
    }

    /**
    * Gets the the second (0 through 59).
    * @exception BiosealException An error has occured during Bioseal library execution.
    * @retval The second (0 through 59).
    */
    int getSecond() {
        int second;
        check_error(id3BiosealDateTime_GetSecond(handle_, &second));
        return second;
    }

    // public methods
    /**
    * Indicates whether the date and/or time is valid.
    * @exception BiosealException An error has occured during Bioseal library execution.
    * @retval true if date and/or time is valid.
    */
    bool isValid() {
        bool result;
        check_error(id3BiosealDateTime_IsValid(handle_, &result));
        return result;
    }

    /**
    * Indicates whether the time is valid.
    * @exception BiosealException An error has occured during Bioseal library execution.
    * @retval true if the time is valid.
    */
    bool isTimeValid() {
        bool result;
        check_error(id3BiosealDateTime_IsTimeValid(handle_, &result));
        return result;
    }

    /**
    * Indicates whether the date is valid.
    * @exception BiosealException An error has occured during Bioseal library execution.
    * @retval true if the date is valid.
    */
    bool isDateValid() {
        bool result;
        check_error(id3BiosealDateTime_IsDateValid(handle_, &result));
        return result;
    }

    /**
    * Indicates whether the date and time are valid.
    * @exception BiosealException An error has occured during Bioseal library execution.
    * @retval true if date and time is valid.
    */
    bool isDateTimeValid() {
        bool result;
        check_error(id3BiosealDateTime_IsDateTimeValid(handle_, &result));
        return result;
    }

    /**
    * Convert the date/time to a string.
    * @param result [out] Automatic format is YYYY-MM-DDTHH:MM:SS, YYYY-MM-DD or HH:MM:SS
    * @exception BiosealException An error has occured during Bioseal library execution.
    * @retval Automatic format is YYYY-MM-DDTHH:MM:SS, YYYY-MM-DD or HH:MM:SS
    */
    void toString(std::string & result) {
        int resultSize = -1;
        auto err = id3BiosealDateTime_ToString(handle_, result.data(), &resultSize);
        if (err == (int)id3BiosealError_InsufficientBuffer) {
            result.resize(resultSize);
            err = id3BiosealDateTime_ToString(handle_, result.data(), &resultSize);
            if (err == 0) { result.resize(resultSize); }
        }
        check_error(err);
    }

    /**
    * Convert the date/time to a string.
    * @exception BiosealException An error has occured during Bioseal library execution.
    * @retval Automatic format is YYYY-MM-DDTHH:MM:SS, YYYY-MM-DD or HH:MM:SS
    */
    std::string toString() {
        std::string result;
        toString(result);
        return result;
    }

};
};