/**
 * Copyright (c) 2021 OceanBase
 * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2.
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 * You may obtain a copy of Mulan PubL v2 at:
 *          http://license.coscl.org.cn/MulanPubL-2.0
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PubL v2 for more details.
 */

#ifndef _OMPK_HANDSHAKE_RESPONSE_H_
#define _OMPK_HANDSHAKE_RESPONSE_H_

#include "lib/string/ob_string.h"
#include "rpc/obmysql/ob_mysql_packet.h"
#include "lib/container/ob_se_array.h"

namespace oceanbase
{
namespace obmysql
{

using common::ObString;

class OMPKHandshakeResponse : public ObMySQLPacket
{
public:
  OMPKHandshakeResponse()
    : capability_(), max_packet_size_(0), character_set_(0), username_(),
      auth_response_(), database_(), auth_plugin_name_(), connect_attrs_() {}

  // reset hand shake response
  void reset();

  // decode hand shake response
  int decode();
  // serialize hand shake response data into buffer
  int serialize(char *buffer, const int64_t length, int64_t &pos) const;
  virtual int64_t get_serialize_size() const;

  inline const ObMySQLCapabilityFlags &get_capability_flags() const { return capability_; }
  inline ObMySQLCapabilityFlags &get_capability_flags() { return capability_; }
  inline bool is_ssl_request() const { return capability_.cap_flags_.OB_CLIENT_SSL; }
  inline uint32_t get_max_packet_size() const { return max_packet_size_; }
  inline uint8_t get_char_set() const { return character_set_; }
  inline const ObString &get_username() const { return username_; }
  inline const ObString &get_auth_response() const { return auth_response_; }
  inline const ObString &get_database() const { return database_; }
  inline const ObString &get_auth_plugin_name() const { return auth_plugin_name_; }
  inline const common::ObIArray<ObStringKV> &get_connect_attrs() const { return connect_attrs_; }
  bool is_obproxy_client_mod() const;

  inline void set_capability_flags(const ObMySQLCapabilityFlags &cap) { capability_ = cap; }
  inline void set_max_packet_size(const uint32_t max_size) { max_packet_size_ = max_size; }
  inline void set_character_set(const uint8_t char_set) { character_set_ = char_set; }
  inline void set_username(const ObString &username) { username_ = username; }
  inline void set_auth_response(const ObString &auth_response) { auth_response_ = auth_response; }
  inline void set_database(const ObString &database) { database_ = database; }
  inline void set_auth_plugin_name(const ObString &plugin_name) { auth_plugin_name_ = plugin_name; }
  int add_connect_attr(const ObStringKV &string_kv);
  void reset_connect_attr() { connect_attrs_.reset(); }

  TO_STRING_KV(K_(capability_.capability), K_(max_packet_size), K_(character_set),
               K_(username), K_(database), K_(auth_plugin_name), K_(connect_attrs));
private:
  uint64_t get_connect_attrs_len() const;

private:
 static const int64_t HAND_SHAKE_RESPONSE_RESERVED_SIZE = 23;
  // capability flags of the client as defined in Protocol::CapabilityFlags.
  ObMySQLCapabilityFlags capability_;
  // max size of a command packet that the client wants to send to the server.
  uint32_t max_packet_size_;
  // connection's default character set as defined in Protocol::CharacterSet.
  uint8_t character_set_;
  // name of the SQL account which client wants to log in
  // this string should be interpreted using the character set
  // indicated by character set field.
  ObString username_;
  // opaque authentication response data generated by
  // Authentication Method indicated by the plugin name field.
  // mostly, client password encrypted by random challenge number.
  ObString auth_response_;
  // initail database for the connection.
  // this string should be interpreted using the character set indicated by character set field.
  ObString database_;
  // the Authentication Method used by the client to generate
  // auth-response value in this packet. This is an UTF-8 string.
  ObString auth_plugin_name_;
  // connection attributes
  common::ObSEArray<ObStringKV, 8> connect_attrs_;
}; // end of class OMPKHandshakeResponse

} // end of namespace obmysql
} // end of namespace oceanbase

#endif /* _OMPK_HANDSHAKE_RESPONSE_H_ */
