// 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 "kudu/util/version_util.h"

#include <regex.h>

#include <mutex>
#include <ostream>
#include <string>
#include <utility>

#include <glog/logging.h>

#include "kudu/gutil/macros.h"
#include "kudu/gutil/strings/numbers.h"
#include "kudu/gutil/strings/strip.h"
#include "kudu/gutil/strings/substitute.h"
#include "kudu/util/status.h"

using std::ostream;
using std::string;
using strings::Substitute;

namespace kudu {

bool Version::operator==(const Version& other) const {
  return this->major == other.major &&
         this->minor == other.minor &&
         this->maintenance == other.maintenance &&
         this->extra_delimiter == other.extra_delimiter &&
         this->extra == other.extra;
}

string Version::ToString() const {
  return extra.empty()
      ? Substitute("$0.$1.$2", major, minor, maintenance)
      : Substitute("$0.$1.$2$3$4", major, minor, maintenance, *extra_delimiter, extra);
}

ostream& operator<<(ostream& os, const Version& v) {
  return os << v.ToString();
}

Status ParseVersion(const string& version_str,
                    Version* v) {
  static regex_t re;
  static std::once_flag once;
  static const char* kVersionPattern =
      "^([[:digit:]]+)\\." // <major>.
      "([[:digit:]]+)\\."  // <minor>.
      "([[:digit:]]+)"     // <maintenance>
      "([.-].*)?$";        // [<delimiter><extra>]
  std::call_once(once, []{
      CHECK_EQ(0, regcomp(&re, kVersionPattern, REG_EXTENDED));
    });

  DCHECK(v);
  const Status invalid_ver_err =
      Status::InvalidArgument("invalid version string", version_str);
  auto v_str = version_str;
  StripWhiteSpace(&v_str);

  regmatch_t matches[5];
  if (regexec(&re, v_str.c_str(), arraysize(matches), matches, 0) != 0) {
    return invalid_ver_err;
  }
#define PARSE_REQUIRED_COMPONENT(idx, lhs)                              \
  {                                                                     \
    int i = (idx);                                                      \
    if (matches[i].rm_so == -1 ||                                       \
        !SimpleAtoi(v_str.substr(matches[i].rm_so,                      \
                                 matches[i].rm_eo - matches[i].rm_so),  \
                    (lhs))) {                                           \
      return invalid_ver_err;                                           \
    }                                                                   \
  }
  Version temp_v;
  PARSE_REQUIRED_COMPONENT(1, &temp_v.major);
  PARSE_REQUIRED_COMPONENT(2, &temp_v.minor);
  PARSE_REQUIRED_COMPONENT(3, &temp_v.maintenance);
#undef PARSE_REQUIRED_COMPONENT
  if (matches[4].rm_so != -1) {
    int extra_comp_off = matches[4].rm_so + 1; // skip the delimiter
    int extra_comp_len = matches[4].rm_eo - extra_comp_off;
    if (extra_comp_len > 0) {
      temp_v.extra_delimiter = v_str[extra_comp_off - 1];
      temp_v.extra = v_str.substr(extra_comp_off, extra_comp_len);
    }
  }
  temp_v.raw_version = version_str;
  *v = std::move(temp_v);

  return Status::OK();
}

} // namespace kudu
