/*
 *  Copyright 2009 The WebRTC Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#ifndef WEBRTC_BASE_FAKENETWORK_H_
#define WEBRTC_BASE_FAKENETWORK_H_

#include <string>
#include <vector>

#include "webrtc/base/network.h"
#include "webrtc/base/messagehandler.h"
#include "webrtc/base/socketaddress.h"
#include "webrtc/base/stringencode.h"
#include "webrtc/base/thread.h"

namespace rtc {

const int kFakeIPv4NetworkPrefixLength = 24;
const int kFakeIPv6NetworkPrefixLength = 64;

// Fake network manager that allows us to manually specify the IPs to use.
class FakeNetworkManager : public NetworkManagerBase,
                           public MessageHandler {
 public:
  FakeNetworkManager() : thread_(Thread::Current()) {}

  typedef std::vector<SocketAddress> IfaceList;

  void AddInterface(const SocketAddress& iface) {
    // Ensure a unique name for the interface if its name is not given.
    AddInterface(iface, "test" + rtc::ToString(next_index_++));
  }

  void AddInterface(const SocketAddress& iface, const std::string& if_name) {
    SocketAddress address(if_name, 0);
    address.SetResolvedIP(iface.ipaddr());
    ifaces_.push_back(address);
    DoUpdateNetworks();
  }

  void RemoveInterface(const SocketAddress& iface) {
    for (IfaceList::iterator it = ifaces_.begin();
         it != ifaces_.end(); ++it) {
      if (it->EqualIPs(iface)) {
        ifaces_.erase(it);
        break;
      }
    }
    DoUpdateNetworks();
  }

  virtual void StartUpdating() {
    ++start_count_;
    if (start_count_ == 1) {
      sent_first_update_ = false;
      thread_->Post(this);
    } else {
      if (sent_first_update_) {
        SignalNetworksChanged();
      }
    }
  }

  virtual void StopUpdating() { --start_count_; }

  // MessageHandler interface.
  virtual void OnMessage(Message* msg) {
    DoUpdateNetworks();
  }

  using NetworkManagerBase::set_enumeration_permission;
  using NetworkManagerBase::set_default_local_addresses;

 private:
  void DoUpdateNetworks() {
    if (start_count_ == 0)
      return;
    std::vector<Network*> networks;
    for (IfaceList::iterator it = ifaces_.begin();
         it != ifaces_.end(); ++it) {
      int prefix_length = 0;
      if (it->ipaddr().family() == AF_INET) {
        prefix_length = kFakeIPv4NetworkPrefixLength;
      } else if (it->ipaddr().family() == AF_INET6) {
        prefix_length = kFakeIPv6NetworkPrefixLength;
      }
      IPAddress prefix = TruncateIP(it->ipaddr(), prefix_length);
      scoped_ptr<Network> net(new Network(it->hostname(),
                                          it->hostname(),
                                          prefix,
                                          prefix_length));
      net->set_default_local_address_provider(this);
      net->AddIP(it->ipaddr());
      networks.push_back(net.release());
    }
    bool changed;
    MergeNetworkList(networks, &changed);
    if (changed || !sent_first_update_) {
      SignalNetworksChanged();
      sent_first_update_ = true;
    }
  }

  Thread* thread_;
  IfaceList ifaces_;
  int next_index_ = 0;
  int start_count_ = 0;
  bool sent_first_update_ = false;

  IPAddress default_local_ipv4_address_;
  IPAddress default_local_ipv6_address_;
};

}  // namespace rtc

#endif  // WEBRTC_BASE_FAKENETWORK_H_
