/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation;
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "ns3/core-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/network-module.h"
#include "ns3/applications-module.h"
#include "ns3/mobility-module.h"
#include "ns3/csma-module.h"
#include "ns3/internet-module.h"
#include "ns3/yans-wifi-helper.h"
#include "ns3/ssid.h"
#include <ns3/buildings-module.h>
#include "ns3/netanim-module.h"
#include "ns3/aodv-module.h"
#include "ns3/olsr-module.h"

using namespace ns3;

NS_LOG_COMPONENT_DEFINE ("ThirdScriptExample");

int main (int argc, char *argv[])
{
  if (true)
    {
      LogComponentEnable ("OnOffApplication", LOG_LEVEL_INFO);
      LogComponentEnable ("PacketSink", LOG_LEVEL_INFO);
      LogComponentEnableAll (LOG_PREFIX_TIME);
      LogComponentEnableAll (LOG_PREFIX_NODE);
      LogComponentEnableAll (LOG_PREFIX_FUNC);
      LogComponentEnable ("ThirdScriptExample", LOG_LEVEL_ALL);
    }

  //Create NodeContainer 
  NodeContainer GatewayNode;
  GatewayNode.Create(1);

  NodeContainer aodvNodes;
  aodvNodes.Add(GatewayNode);
  aodvNodes.Create(1);

  NodeContainer olsrNodes;
  olsrNodes.Add(GatewayNode);
  olsrNodes.Create(1);

  // Create Wifi Settings 
  YansWifiChannelHelper channel = YansWifiChannelHelper::Default ();
  YansWifiPhyHelper phy = YansWifiPhyHelper::Default ();
  phy.SetChannel (channel.Create ());


  WifiHelper wifi;
  wifi.SetRemoteStationManager ("ns3::AarfWifiManager");

  WifiMacHelper mac;
  //mac.SetType("ns3::AdhocWifiMac");
  Ssid ssid = Ssid ("ns-3-ssid");
  mac.SetType ("ns3::StaWifiMac",
               "Ssid", SsidValue (ssid),
               "ActiveProbing", BooleanValue (false));
  

    // Create dtn device 
  NetDeviceContainer olsrDevices;
  olsrDevices = wifi.Install(phy, mac, olsrNodes.Get(1));

  // Create Aodv device
  NetDeviceContainer aodvDevices;
  aodvDevices = wifi.Install(phy, mac, aodvNodes.Get(1));
  
  //mac.SetType("ns3::AdhocWifiMac");
  mac.SetType ("ns3::ApWifiMac",
               "Ssid", SsidValue (ssid));

  NetDeviceContainer gatewayDevice;
  gatewayDevice = wifi.Install(phy, mac, GatewayNode);


  // Set Aodv Helper
  AodvHelper aodv;

  //Set OLSR Helper
  OlsrHelper olsr;
  
  // Set ListRoutingHelper
  Ipv4ListRoutingHelper list;
  list.Add(aodv, 10);

  Ipv4ListRoutingHelper list2;
  list2.Add(olsr, 10);

  Ipv4ListRoutingHelper list3;
  list3.Add(aodv, 10);
  list3.Add(olsr, 10);

  /* Create Internet (1) */
  InternetStackHelper internet;
  internet.SetRoutingHelper(list);
  internet.Install(aodvNodes.Get(1));

  internet.Reset();
 
  internet.SetRoutingHelper(list2);
  internet.Install(olsrNodes.Get(1));

  internet.Reset();
  
  internet.SetRoutingHelper (list3);
  internet.Install (GatewayNode);


  Ipv4AddressHelper address;

  address.SetBase ("10.1.1.0", "255.255.255.0");
  Ipv4InterfaceContainer olsrInterfaces;
  olsrInterfaces = address.Assign(olsrDevices);

  address.SetBase ("10.1.2.0", "255.255.255.0");
  Ipv4InterfaceContainer aodvInterfaces;
  aodvInterfaces = address.Assign(aodvDevices);

  /** set Application2 **/
  
  //sink or server setup
  PacketSinkHelper sink ("ns3::UdpSocketFactory",
                         InetSocketAddress (Ipv4Address::GetAny (), 80));
  ApplicationContainer apps_sink = sink.Install (olsrNodes.Get (1));
  apps_sink.Start (Seconds (0.0));
  apps_sink.Stop (Seconds (100.0));

  // Client setup
  OnOffHelper onoff1 ("ns3::UdpSocketFactory",
                      Address (InetSocketAddress (olsrInterfaces.GetAddress (1), 80)));
  std::string rate = "0.512kbps";
  onoff1.SetConstantRate (DataRate (rate));
  onoff1.SetAttribute ("PacketSize", UintegerValue (64));
  ApplicationContainer apps1 = onoff1.Install (aodvNodes.Get (1));
  apps1.Start (Seconds (2.0));
  apps1.Stop (Seconds (100.0));
  
  /* Mobility Settings */
  MobilityHelper mobility;

  mobility.SetPositionAllocator ("ns3::GridPositionAllocator",
                                 "MinX", DoubleValue (0.0),
                                 "MinY", DoubleValue (0.0),
                                 "DeltaX", DoubleValue (5.0),
                                 "DeltaY", DoubleValue (10.0),
                                 "GridWidth", UintegerValue (8),
                                 "LayoutType", StringValue ("RowFirst"));

  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
  mobility.Install (aodvNodes.Get(1));
  mobility.Install (GatewayNode);
  mobility.Install (olsrNodes.Get(1));
  
  //Ipv4GlobalRoutingHelper::PopulateRoutingTables ();

  Simulator::Stop (Seconds (100.0));

  AnimationInterface anim ("wireless-animation.xml");
  
  // iro to moji no settei

  anim.UpdateNodeDescription (aodvNodes.Get(1), "AODV"); // Optional
  anim.UpdateNodeColor (aodvNodes.Get(1), 255, 0, 0); // Optional

  anim.UpdateNodeDescription (olsrNodes.Get(1), "OLSR"); // Optional
  anim.UpdateNodeColor (olsrNodes.Get(1), 0, 0, 255); // Optional 

  anim.UpdateNodeDescription (GatewayNode.Get(0), "GateWay"); // Optional
  anim.UpdateNodeColor (GatewayNode.Get(0), 0, 255, 0); // Optional 

  anim.EnablePacketMetadata (); // Optional
  anim.EnableIpv4RouteTracking ("routingtable-wireless.xml", Seconds (0), Seconds (5), Seconds (0.25)); //Optional
  anim.EnableWifiMacCounters (Seconds (0), Seconds (100)); //Optional
  anim.EnableWifiPhyCounters (Seconds (0), Seconds (100)); //Optional

  Simulator::Run ();
  Simulator::Destroy ();
  return 0;
}
