<?php
date_default_timezone_set('America/Los_Angeles'); ?><!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Mesh Network Topo Map</title>

<!--
                                                                                
                                                                                
                            &, /@              #@  @                            
                              /@@/@*         @%@@@                              
                                     #    ,                                     
                                        @                                       
                                @   #   %  ,/  ./                               
                             .@@@@&    /&     @@@@@                             
                           *.   ,      &&/      #   *.                          
                                       #@@                                      
                                      @#%#.                                     
                                      @(@#@                                     
                                     @*.@#.,                                    
                                    ,/.#@#%@                                    
                                    @@#@@#&@#                                   
                                   #.@&.@ %/&.           CQ CQ de K9RCP         
                                  ,%.,(*@ @@ @                                  
                                  @(   %@@  (*%                                 
                                 @@(@&*@@#(@&(@/                                
                                &/#. @ %@ /* # @                                
                               *@  %(  %@   @,  @                               
                              .@ #* .& %@. @  % .@                              
                              @*(     @%@*@     @#&                             
                             @(#/%@@&%(@@%%&@@@#/@&#                            
                            @( .&    @.&@/(%    @  @/                           
                           @@    @@.   @@/   ##@    @.                          
                          #@   @. @    @@%   ,% (%  .@                          
                         /@ @.     &.  @@%  #/     (%*@                         
                         &          #* @@% @.         /*                        
                                     *%@@&@                                     
                                      .@@@.//                                   
                                                                                
-->

    <style>

    #app {
      display: flex;
      display: -webkit-flex;
      flex-direction: column;
      -webkit-flex-direction: column;
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
    }

    #header {
      flex: 0 0 auto;
      -webkit-flex: 0 0 auto;
      line-height: 1.3;
    }

    #panes {
      display: flex;
      display: -webkit-flex;
      flex: 1 1 auto;
      -webkit-flex: 1 1 auto;
    }

    #graph {
      display: flex;
      display: -webkit-flex;
      flex-direction: column;
      -webkit-flex-direction: column;
    }
    
    #options {
      flex: 0 0 auto;
      -webkit-flex: 0 0 auto;
    }
    
    #output {
      flex: 1 1 auto;
      -webkit-flex: 1 1 auto;
      position: relative;
      overflow: auto;
    }
    
    
    #editor {
      border-right: 1px solid #ccc;
    }

    #header {
      background: #eee;
      border-bottom: 1px solid #ccc;
      padding: 8px;
      text-align: center;
    }
    
    #header b {
      font-size: 18px;
    }
    
    #options {
      background: #eee;
      border-bottom: 1px solid #ccc;
      padding: 8px;
    }
    
    #options label {
      margin-right: 8px;
    }
    
    #options #raw.disabled {
      opacity: 0.5;
    }
    
    #output svg {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
    }
    
    #output #text {
      font-size: 12px;
      font-family: monaco, courier, monospace;
      white-space: pre;
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      overflow: auto;
    }
    
    #output img {
      display: block;
      margin: 0 auto;
    }
    
    #output.working svg, #output.error svg,
    #output.working #text, #output.error #text,
    #output.working img, #output.error img {
      opacity: 0.4;
    }
    
    #output.error #error {
      display: inherit;
    }
    
    #output #error {
      display: none;
      position: absolute;
      top: 20px;
      left: 20px;
      margin-right: 20px;
      background: red;
      color: white;
      z-index: 1;
    }

    .gutter {
      background-color: #eee;
      background-repeat: no-repeat;
      background-position: 50%;
    }

    .gutter.gutter-horizontal {
      background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg==');
      cursor: ew-resize;
    }

    .split {
      -webkit-box-sizing: border-box;
      -moz-box-sizing: border-box;
      box-sizing: border-box;

      overflow-y: auto;
      overflow-x: hidden;
    }

    .split.split-horizontal, .gutter.gutter-horizontal {
      height: 100%;
      float: left;
    }
    
    </style>
  </head>
  <body>
    
    <div id="app">
      <div id="header">
	<b>WVMN Topology - <?php echo date("F j, Y, g:i a"); ?></b>
      </div>
      <div id="panes">
        <div id="editor"  hidden>
	<?php
$fp = fsockopen("10.204.114.225", 2004, $errno, $errstr, 30);
$data = "";
if (!$fp) {
    echo "$errstr ($errno)<br />\n";
} else {
    while (!feof($fp)) {
        $data .= fgets($fp, 128);
    }
    fclose($fp);
}


if (!function_exists('str_contains')) {
    function str_contains($haystack, $needle): bool {
        if ( is_string($haystack) && is_string($needle) ) {
            return '' === $needle || false !== strpos($haystack, $needle);
        } else {
            return false;
        }
    }
}



$ips = json_decode(file_get_contents("./ips.host"), TRUE);
$ar = explode("\n", $data);

$checkNodes = array();

$data = "";

foreach ($ar as &$value) {
        $ip = explode('"', $value)[1];

if (filter_var($ip, FILTER_VALIDATE_IP && !isset($ips[$ip]))) {
        $ips[$ip] = "NULL";

}
        if (!str_contains($value, 'HNA') && !str_contains($value, 'diamond')) {
	        if (str_contains($value, 'label')) {
			$dr = explode('];', $value);
			$val = explode('"', explode('label="', $value)[1])[0];
			if ($val < 0.98) { $color = "blue"; $pwidth = 1; }
			if ($val > 0.99) { $color = "green"; $pwidth = 2.5; }
			if ($val > 3.00) { $color = "yellow";$pwidth = 2.5; }
			if ($val > 4.00) { $color = "orange"; $pwidth = 3.5; }
			if ($val > 6.00) { $color = "red"; $pwidth = 5; }
			if ($val == "INFINITE") { $color = "red"; $pwidth = 8; }

//$dr[0] = "10.166.72.127" -> "10.138.41.208"[label="0.100"];

			$da = explode('"', $dr[0]);
			if (!isset($checkNodes[$da[3]."-".$da[1]])) {
				$data .= $dr[0].', penwidth='.$pwidth.' color="'.$color.'"];'."\n";
				$checkNodes[$da[1]."-".$da[3]] = "TRUE";
			} else {
				$data .= $dr[0].', penwidth='.$pwidth.' color="'.$color.'"];'."\n";
				
			}
		} else {
                	$data .= $value."\n";
		}
        }
}
foreach ($ips as $key => $value) {
	if(filter_var($ips[$key], FILTER_VALIDATE_IP) || $ips[$key] == "NULL") {
	        $ips[$key] = gethostbyaddr($key);
	}
        $data = str_replace($key, $ips[$key], $data);
}
file_put_contents("./ips.host", json_encode($ips));

//print_r($checkNodes);

echo $data;

?>
	</div>
        <div id="graph">
          <div id="options" hidden>
            <label id="engine">
              Engine:
              <select>
                <option>circo</option>
                <option selected>dot</option>
                <option>fdp</option>
                <option>neato</option>
                <option>osage</option>
                <option>twopi</option>
              </select>
            </label>
            
            <label id="format">
              Format:
              <select>
                <option selected>svg</option>
                <option>png-image-element</option>
                <option>json</option>
                <option>xdot</option>
                <option>plain</option>
                <option>ps</option>
              </select>
            </label>
            
            <label id="raw">
              <input type="checkbox"> Show raw output
            </label>
          </div>
          <div id="output">
            <div id="error"></div>
          </div>
        </div>
      </div>
    </div>
    
    <script src="./js/ace.js"></script>
    <script src="./js/viz.js"></script>
    <script src="./js/fabric.min.js"></script>
    <script src="./js/split.min.js"></script>
    <script src="./js/svg-pan-zoom.min.js"></script>
    <script>

    var beforeUnloadMessage = null;

    var resizeEvent = new Event("paneresize");
    Split(['#editor', '#graph'], {
      sizes: [0, 100],
      onDragEnd: function() { 
        var svgOutput = document.getElementById("svg_output");
        if (svgOutput != null) {
          svgOutput.dispatchEvent(resizeEvent);
        }
      }
    });
    
    var editor = ace.edit("editor");
    editor.getSession().setMode("ace/mode/dot");

    var parser = new DOMParser();
    var worker;
    var result;

    function updateGraph() {
      if (worker) {
        worker.terminate();
      }

      document.querySelector("#output").classList.add("working");
      document.querySelector("#output").classList.remove("error");

      worker = new Worker("./worker.js");

      worker.onmessage = function(e) {
        document.querySelector("#output").classList.remove("working");
        document.querySelector("#output").classList.remove("error");
        
        result = e.data;
        
        updateOutput();
      }

      worker.onerror = function(e) {
        document.querySelector("#output").classList.remove("working");
        document.querySelector("#output").classList.add("error");
        
        var message = e.message === undefined ? "An error occurred while processing the graph input." : e.message;
        
        var error = document.querySelector("#error");
        while (error.firstChild) {
          error.removeChild(error.firstChild);
        }
        
        document.querySelector("#error").appendChild(document.createTextNode(message));
        
        console.error(e);
        e.preventDefault();
      }
      
      var params = {
        src: editor.getSession().getDocument().getValue(),
        options: {
          engine: document.querySelector("#engine select").value,
          format: document.querySelector("#format select").value
        }
      };
      
      // Instead of asking for png-image-element directly, which we can't do in a worker,
      // ask for SVG and convert when updating the output.
      
      if (params.options.format == "png-image-element") {
        params.options.format = "svg";
      }
      
      worker.postMessage(params);
    }
    
    function updateOutput() {
      var graph = document.querySelector("#output");

      var svg = graph.querySelector("svg");
      if (svg) {
        graph.removeChild(svg);
      }

      var text = graph.querySelector("#text");
      if (text) {
        graph.removeChild(text);
      }

      var img = graph.querySelector("img");
      if (img) {
        graph.removeChild(img);
      }
      
      if (!result) {
        return;
      }
      
      if (document.querySelector("#format select").value == "svg" && !document.querySelector("#raw input").checked) {
        var svg = parser.parseFromString(result, "image/svg+xml").documentElement;
        svg.id = "svg_output";
        graph.appendChild(svg);

        panZoom = svgPanZoom(svg, {
          zoomEnabled: true,
          controlIconsEnabled: true,
          fit: true,
          center: true,
          minZoom: 0.1
        });

        svg.addEventListener('paneresize', function(e) {
          panZoom.resize();
        }, false);
        window.addEventListener('resize', function(e) {
          panZoom.resize();
        });
      } else if (document.querySelector("#format select").value == "png-image-element") {
        var image = Viz.svgXmlToPngImageElement(result);
        graph.appendChild(image);
      } else {
        var text = document.createElement("div");
        text.id = "text";
        text.appendChild(document.createTextNode(result));
        graph.appendChild(text);
      }
    }

    editor.on("change", function() {
      updateGraph();
      beforeUnloadMessage = "Your changes will not be saved.";
    });
    
    window.addEventListener("beforeunload", function(e) {
      return beforeUnloadMessage;
    });
    
    document.querySelector("#engine select").addEventListener("change", function() {
      updateGraph();
    });

    document.querySelector("#format select").addEventListener("change", function() {
      if (document.querySelector("#format select").value === "svg") {
        document.querySelector("#raw").classList.remove("disabled");
        document.querySelector("#raw input").disabled = false;
      } else {
        document.querySelector("#raw").classList.add("disabled");
        document.querySelector("#raw input").disabled = true;
      }
      
      updateGraph();
    });

    document.querySelector("#raw input").addEventListener("change", function() {
      updateOutput();
    });
    
    updateGraph();
    
    </script>
    
  </body>
</html>