{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Build a simulation using the Python API\n",
    "\n",
    "© Crown-owned copyright 2024, Defence Science and Technology Laboratory UK\n",
    "\n",
    "Currently, this notebook manipulates the simulation by directly placing objects inside of the attributes of the network and domain. It should be refactored when proper methods exist for adding these objects."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Import the Simulation class"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from primaite.simulator.sim_container import Simulation\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Create an empty simulation. By default this has a network with no nodes or links, and a domain controller with no accounts.\n",
    "\n",
    "Let's use the simulation's `describe_state()` method to verify that it is empty."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "my_sim = Simulation()\n",
    "net = my_sim.network\n",
    "my_sim.describe_state()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Add nodes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from primaite.simulator.network.hardware.nodes.host.computer import Computer\n",
    "from primaite.simulator.network.hardware.nodes.host.server import Server"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "my_pc = Computer(hostname=\"Computer\", ip_address=\"192.168.1.10\", subnet_mask=\"255.255.255.0\")\n",
    "net.add_node(my_pc)\n",
    "my_server = Server(hostname=\"Server\", ip_address=\"192.168.1.11\", subnet_mask=\"255.255.255.0\")\n",
    "net.add_node(my_server)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Connect the nodes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from primaite.simulator.network.hardware.nodes.host.host_node import NIC\n",
    "from primaite.simulator.network.hardware.nodes.network.switch import Switch\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "my_switch = Switch(hostname=\"switch1\", num_ports=12)\n",
    "net.add_node(my_switch)\n",
    "\n",
    "pc_nic = NIC(ip_address=\"130.1.1.1\", gateway=\"130.1.1.255\", subnet_mask=\"255.255.255.0\")\n",
    "my_pc.connect_nic(pc_nic)\n",
    "\n",
    "server_nic = NIC(ip_address=\"130.1.1.2\", gateway=\"130.1.1.255\", subnet_mask=\"255.255.255.0\")\n",
    "my_server.connect_nic(server_nic)\n",
    "\n",
    "net.connect(pc_nic, my_switch.network_interface[1])\n",
    "net.connect(server_nic, my_switch.network_interface[2])\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Add files and folders to nodes\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from primaite.simulator.file_system.file_type import FileType\n",
    "from primaite.simulator.file_system.file_system import File\n",
    "from primaite.simulator.system.core.sys_log import SysLog"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "my_pc_downloads_folder = my_pc.file_system.create_folder(\"downloads\")\n",
    "my_pc_downloads_folder.add_file(File(name=\"firefox_installer.zip\",folder_id=\"Test\", folder_name=\"downloads\" ,file_type=FileType.ZIP, sys_log=SysLog(hostname=\"Test\")))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "my_server_folder = my_server.file_system.create_folder(\"static\")\n",
    "my_server.file_system.create_file(\"favicon.ico\", file_type=FileType.PNG)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Add applications to nodes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from pathlib import Path\n",
    "from primaite.simulator.system.applications.application import Application, ApplicationOperatingState\n",
    "from primaite.simulator.system.software import SoftwareHealthState, SoftwareCriticality\n",
    "from primaite.simulator.file_system.file_system import FileSystem\n",
    "from primaite.utils.validation.ip_protocol import PROTOCOL_LOOKUP\n",
    "from primaite.utils.validation.port import PORT_LOOKUP\n",
    "\n",
    "\n",
    "# no applications exist yet so we will create our own.\n",
    "class MSPaint(Application, identifier=\"MSPaint\"):\n",
    "    def describe_state(self):\n",
    "        return super().describe_state()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "mspaint = MSPaint(name = \"mspaint\", health_state_actual=SoftwareHealthState.GOOD, health_state_visible=SoftwareHealthState.GOOD, criticality=SoftwareCriticality.MEDIUM, port=PORT_LOOKUP[\"HTTP\"], protocol = PROTOCOL_LOOKUP[\"NONE\"],operating_state=ApplicationOperatingState.RUNNING,execution_control_status='manual', file_system=FileSystem(sys_log=SysLog(hostname=\"Test\"), sim_root=Path(__name__).parent),)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "my_pc.applications[mspaint.uuid] = mspaint"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Create a domain account"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from primaite.simulator.domain.account import Account, AccountType\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "acct = Account(username=\"admin\", password=\"admin12\", account_type=AccountType.USER)\n",
    "my_sim.domain.accounts[acct.uuid] = acct"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Verify that the state dictionary contains no non-serialisable objects."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "my_sim.describe_state()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import json\n",
    "json.dumps(my_sim.describe_state())"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": ".venv",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
