<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Network IP Scanner</title>
    <style>
      body {
        font-family: Arial, sans-serif;
        margin: 20px;
      }
      .indicator {
        width: 15px;
        height: 15px;
        border-radius: 50%;
        margin-left: 10px;
        display: inline-block;
      }
      .online {
        background-color: green;
      }
      .offline {
        background-color: red;
      }
      .ip-row {
        display: flex;
        justify-content: space-between;
        margin-bottom: 10px;
      }
      .ip-item {
        display: flex;
        align-items: center;
      }
      .ip-link {
        margin-right: 10px;
      }
      #scan-button {
        padding: 10px 20px;
        background-color: #535353;
        color: white;
        border: none;
        cursor: pointer;
        font-size: 16px;
        margin-bottom: 20px;
      }
      #scan-button:hover {
        background-color: #929292;
      }
      #status-message {
        font-size: 16px;
        font-weight: bold;
        color: black;
        display: inline-block;
        margin-left: 10px;
      }
      #port-input {
        padding: 5px;
        font-size: 16px;
        margin-bottom: 20px;
      }
    </style>
  </head>
  <body>
    <h1>Network IP Scanner</h1>
    
    <label for="port-input">Enter Port: </label>
    <input type="number" id="port-input" value="5500" min="1" max="65535">
    
    <br/>
    
    <button id="scan-button">SCAN</button>
    <span id="status-message"></span>
    <div id="ip-list"></div>

    <script>
      const TIMEOUT = 10000;  
      const IP_RANGE_START = 0;
      const IP_RANGE_END = 255;
      const IP_PREFIX = '10.0.1.';

      
      function checkIPStatus(ip, port) {
        return new Promise((resolve, reject) => {
          const url = `http://${ip}:${port}`;  // Use backticks for dynamic URL
          const controller = new AbortController();
          const timeoutId = setTimeout(() => controller.abort(), TIMEOUT);

          // Use GET instead of HEAD to avoid network restrictions
          fetch(url, { method: 'GET', signal: controller.signal })
            .then(response => {
              clearTimeout(timeoutId);
              resolve(response.ok);
            })
            .catch((error) => {
              clearTimeout(timeoutId);
              reject(error);
            });
        });
      }

      // Function to create an IP row with its status
      function createIPRow(ip, isOnline, port) {
        const ipListContainer = document.getElementById('ip-list');

        const row = document.createElement('div');
        row.classList.add('ip-row');
        row.dataset.ip = ip;  // Store IP in data attribute

        const ipItem = document.createElement('div');
        ipItem.classList.add('ip-item');

        const link = document.createElement('a');
        if (isOnline) {
          // Only make the link clickable if it's a valid HTTP service
          link.href = `http://${ip}:${port}`;
          link.textContent = ip;
        } else {
          link.textContent = `${ip} (Offline)`;
          link.style.color = 'grey';
        }
        link.classList.add('ip-link');

        const indicator = document.createElement('span');
        indicator.classList.add('indicator');
        indicator.classList.add(isOnline ? 'online' : 'offline');

        ipItem.appendChild(link);
        ipItem.appendChild(indicator);
        row.appendChild(ipItem);
        ipListContainer.appendChild(row);

        // If the IP is offline, remove it after scanning is done
        if (!isOnline) {
          row.style.display = 'none';  // Hide offline IPs
        }
      }

      // Function to process IPs in a sequential manner and display them in batches of 3 per row
      async function processIPs() {
        const ipListContainer = document.getElementById('ip-list');
        const statusMessage = document.getElementById('status-message');
        const portInput = document.getElementById('port-input');  // Get port value from input field
        const port = portInput.value || 5500;  // Use default port if empty

        ipListContainer.innerHTML = '';  // Clear previous content
        statusMessage.textContent = 'Scanning...';  // Display "Scanning..." message

        // Process IPs from 10.0.1.0 to 10.0.1.255
        const ipPromises = [];
        for (let i = IP_RANGE_START; i <= IP_RANGE_END; i++) {
          const ip = `${IP_PREFIX}${i}`;  // Corrected dynamic IP creation

          // Check each IP and create its row with its online/offline status
          ipPromises.push(
            checkIPStatus(ip, port)
              .then(isOnline => createIPRow(ip, isOnline, port))
              .catch(() => createIPRow(ip, false, port))  // If error occurs, mark as offline
          );
        }

        // Wait for all IPs to be processed and displayed
        await Promise.all(ipPromises);

        statusMessage.textContent = 'Finished scanning.';  // Change message to "Finished scanning."
      }

      // Event listener for the scan button
      document.getElementById('scan-button').addEventListener('click', processIPs);
    </script>
  </body>
</html>
