/*
 * Copyright 2015 Twitter, Inc.
 *
 * Licensed 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.
 */

///////////////////////////////////////////////////////////////////////////////
//
// This file defines the ZKClient class.
// ZKClient is used by all services inside heron to communicate with zoo-keeper.
// ZKClient works over libevent and uses async version of the zk client library
// NOTE:- Currently we use only single threaded zoo-keeper library
//
///////////////////////////////////////////////////////////////////////////////
#ifndef ZKCLIENT_H_
#define ZKCLIENT_H_

#include <zookeeper/proto.h>
#include <zookeeper/zookeeper.h>
#include <string>
#include <vector>
#include "basics/basics.h"
#include "network/network.h"
#include "threads/threads.h"

/*
 * ZKClient class definition
 */
class ZKClient {
 public:
  // Helper struct to pass watch events
  struct ZkWatchEvent {
    sp_int32 type;
    sp_int32 state;
    std::string path;
  };

  // Constructor/Destructor
  ZKClient(const std::string& hostportlist, EventLoop* eventLoop);

  // If a global_watcher is provided, the clients can watch on session events.
  // Right now only SessionExpired event is notified, but could have others
  // in the future. global_watcher_cb should be a PermanentCallback.
  ZKClient(const std::string& hostportlist, EventLoop* eventLoop,
           VCallback<ZkWatchEvent> global_watcher_cb);

  virtual ~ZKClient();

  // Queries whether the node exists in the zk. If _watcher is not null
  // sets a watcher that will be called when the node changes.
  // _cb is called with the
  // status code after this call completes. A ZOK status code means
  // that the node exists. Otherwise there was some error
  virtual void Exists(const std::string& _node, VCallback<> _watcher, VCallback<sp_int32> _cb);
  // same as above if we are not interested in watching
  virtual void Exists(const std::string& _node, VCallback<sp_int32> _cb);

  // creates a node. The node is created at _node. If _is_ephemeral is set,
  // then the node is created as a ephemeral node. _cb is called with
  // the status code after the Create completes.
  virtual void CreateNode(const std::string& _node, const std::string& _value, bool _is_ephimeral,
                          VCallback<sp_int32> _cb);

  // deletes a node. _cb is called with the status code after Delete completes
  virtual void DeleteNode(const std::string& _node, VCallback<sp_int32> _cb);

  // Gets the data at a node. The data is filled in the _data provided
  // by the caller. If _version is not null, we store the version there.
  // If _watcher is not null, we set a watch on this node and call the _watcher
  // function when the node changes.
  // _cb is called with the result code after get completes.
  virtual void Get(const std::string& _node, std::string* _data, sp_int32* _version,
                   VCallback<> _watcher, VCallback<sp_int32> _cb);
  virtual void Get(const std::string& _node, std::string* _data, sp_int32* _version,
                   VCallback<sp_int32> _cb);
  // Same as above except we dont care about the version
  virtual void Get(const std::string& _node, std::string* _data, VCallback<sp_int32> _cb);

  // Sets the data at a node.
  virtual void Set(const std::string& _node, const std::string& _data, sp_int32 _version,
                   VCallback<sp_int32> _cb);
  // Same as above except brute force the write
  virtual void Set(const std::string& _node, const std::string& _data, VCallback<sp_int32> _cb);

  // lists all the children. The children will be filled at _children list created
  // by the caller.
  virtual void GetChildren(const std::string& _node, std::vector<std::string>* _children,
                           VCallback<sp_int32> _cb);

  // friend functions
  friend void CallGlobalWatcher(zhandle_t* _zh, sp_int32 _type, sp_int32 _state, const char* _path,
                                void* _context);
  friend void StringCompletionWatcher(sp_int32 _rc, const char* _name, const void* _data);
  friend void VoidCompletionWatcher(sp_int32 _rc, const void* _data);
  friend void GetCompletionWatcher(sp_int32 _rc, const char* _value, int _value_len,
                                   const struct Stat* _stat, const void* _data);
  friend void SetCompletionWatcher(sp_int32 _rc, const struct Stat* _stat, const void* _data);
  friend void GetChildrenCompletionWatcher(sp_int32 _rc, const struct String_vector* _strings,
                                           const void* _data);

  // Util functions to convert from the codes to strings
  static const std::string type2String(sp_int32 state);
  static const std::string state2String(sp_int32 state);

 protected:
  // A empty constructor for test purposes ONLY. Enables us to create a
  // MockZkClient without worrying about the actual private member variables.
  ZKClient()
      : zk_handle_(NULL),
        eventLoop_(NULL),
        client_global_watcher_cb_(VCallback<ZkWatchEvent>()) {}

 private:
  // the global watcher
  void GlobalWatcher(zhandle_t* _zh, sp_int32 _type, sp_int32 _state, const char* _path);

  // The function that actually inits the handle
  void InitZKHandle();

  // We wrap all user zk calls with this completion function
  // This completion function runs in the context of the
  // zk completion thread. It basically calls the piper
  // to execute the cb in eventLoop thread
  void ZkActionCb(sp_int32 rc, VCallback<sp_int32> cb);

  // This is the watcher function that gets called
  // when a node changes
  void ZkWatcherCb(VCallback<> cb);

  // Common functionality for c`tors. Should be called only once from c`tor
  void Init();
  // Sends events to clients, if client global watcher is set.
  void SendWatchEvent(const ZkWatchEvent& event);

  clientid_t zk_clientid_;
  zhandle_t* zk_handle_;
  EventLoop* eventLoop_;
  std::string hostportlist_;

  // We use libzookeeper_mt as our zk library. This means that
  // zk callbacks are all executed in the context of a zk thread.
  // Piper are how they communicate it accross to our main thread
  Piper* piper_;
  // A callback to notify the clients of this class about global session events.
  VCallback<ZkWatchEvent> client_global_watcher_cb_;
};

#endif  // ZKCLIENT_H_
