using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using ISPChk.Models;
using System.Net;

namespace ISPChk.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class HostController : ControllerBase
    {
        private readonly ISPChkContext _context;
        private readonly INetworkTest _networkTest;

        public HostController(ISPChkContext context, INetworkTest networkTest)
        {
            _context = context;
            _networkTest = networkTest;
        }

        // GET: api/Host
        [HttpGet]
        public async Task<ActionResult<IEnumerable<Host>>> GetHosts()
        {
            return await _context.Hosts.ToListAsync();
        }

        // GET: api/Host/5
        [HttpGet("{id}")]
        public async Task<ActionResult<Host>> GetHost(long id)
        {
            var host = await _context.Hosts.FindAsync(id);

            if (host == null)
            {
                return NotFound();
            }

            return host;
        }

        // GET: api/Host/5
        [HttpGet("{id}/pings/{start}/{end?}")]
        public async Task<ActionResult<IEnumerable<PingItem>>> GetPingsByTimeSpan(long id, long start, long end)
        {
            System.Diagnostics.Debug.WriteLine("called id:" + id + " start:" + start + " end:" + end);
            var host = await _context.Hosts.FindAsync(id);

            if (host == null)
            {
                return NotFound();
            }

            var startTime = DateTimeOffset.FromUnixTimeMilliseconds(start).DateTime;
            var endTime = DateTimeOffset.FromUnixTimeMilliseconds(end).DateTime;

            var pis = _context.Entry(host).Collection(h => h.PingItems).Query().Where(p => p.Date > startTime).ToList();

            return pis;
        }

        // PUT: api/Host/5
        // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
        [HttpPut("{id}")]
        public async Task<IActionResult> PutHost(long id, Host host)
        {
            if (id != host.HostId)
            {
                return BadRequest();
            }

            _context.Entry(host).State = EntityState.Modified;

            try
            {
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!HostExists(id))
                {
                    return NotFound();
                }
                else
                {
                    throw;
                }
            }

            return NoContent();
        }

        // POST: api/Host
        // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
        [HttpPost]
        public async Task<ActionResult<Host>> PostHost(Host host)
        {
            IPAddress ipAddr;
            if (!IPAddress.TryParse(host.HostName, out ipAddr))
            {
                try {
                    IPHostEntry hostInfo = Dns.GetHostEntry(host.HostName);
                } catch(System.Net.Sockets.SocketException e)
                {
                    return BadRequest(new { errmsg = "Could not resolve hostname." });
                }
            } else
            {
                if(ipAddr.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork && host.IPv6 == true ||
                    ipAddr.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6 && host.IPv6 == false)
                {
                    return BadRequest(new { errmsg = "Given IP was not of correct family." });
                }
            }
            _context.Hosts.Add(host);
            await _context.SaveChangesAsync();

            _networkTest.AddHost(host);

            return CreatedAtAction("GetHost", new { id = host.HostId }, host);
        }

        // DELETE: api/Host/5
        [HttpDelete("{id}")]
        public async Task<IActionResult> DeleteHost(long id)
        {
            var host = await _context.Hosts.FindAsync(id);
            if (host == null)
            {
                return NotFound();
            }

            _context.Hosts.Remove(host);
            await _context.SaveChangesAsync();

            return NoContent();
        }

        private bool HostExists(long id)
        {
            return _context.Hosts.Any(e => e.HostId == id);
        }
    }
}
