import 'dart:async';
import 'dart:isolate';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
import 'package:web_socket_channel/status.dart' as status;
import 'package:network_info_plus/network_info_plus.dart';
import 'package:flutter/foundation.dart' show kIsWeb;

import '../utils/web_socket_server.dart';

class WebSocketWidget extends StatefulWidget {
  @override
  _WebSocketWidgetState createState() => _WebSocketWidgetState();
}

class _WebSocketWidgetState extends State<WebSocketWidget> {
  WebSocketChannel? _channel;
  TextEditingController _controller = TextEditingController();
  TextEditingController _urlController = TextEditingController(text: 'ws://localhost:8080');
  List<String> _messages = [];
  Isolate? _serverIsolate;
  bool _isServerRunning = false;
  String? _localIpAddress;

  @override
  void initState() {
    super.initState();
    _getLocalIpAddress().then((ip) {
      setState(() {
        _localIpAddress = ip;
        _urlController.text = 'ws://$_localIpAddress:8080';
      });
    });
  }

  Future<String> _getLocalIpAddress() async {
    if (kIsWeb) {
      return '127.0.0.1'; // Web does not support getting the local IP address
    }

    if (Platform.isAndroid || Platform.isIOS) {
      final info = NetworkInfo();
      String? ip = await info.getWifiIP();
      return ip ?? '127.0.0.1'; // Fallback to localhost if no IP is found
    }

    for (var interface in await NetworkInterface.list()) {
      for (var addr in interface.addresses) {
        if (addr.type == InternetAddressType.IPv4 && !addr.isLoopback) {
          return addr.address;
        }
      }
    }
    return '127.0.0.1'; // Fallback to localhost if no IP is found
  }

  void _startServer() async {
    final receivePort = ReceivePort();
    _serverIsolate = await Isolate.spawn(webSocketServer, receivePort.sendPort);
    receivePort.listen((message) {
      print(message);
      setState(() {
        _isServerRunning = true;
      });
    });
  }

  void _stopServer() {
    _serverIsolate?.kill(priority: Isolate.immediate);
    setState(() {
      _isServerRunning = false;
    });
  }

  void _joinWebSocket() {
    if (_channel != null) {
      _channel!.sink.close();
    }
    setState(() {
      _channel = WebSocketChannel.connect(Uri.parse(_urlController.text));
      _channel!.stream.listen((message) {
        setState(() {
          _messages.add(message);
        });
      });
    });
  }

  void _sendMessage(String message) {
    if (_channel != null) {
      _channel!.sink.add(message);
      setState(() {
        _messages.add('You: $message'); // Display the sent message
      });
    }
  }

  void _closeConnection() {
    if (_channel != null) {
      _channel!.sink.close(status.goingAway);
      setState(() {
        _channel = null;
        _messages.clear();
      });
    }
  }

  @override
  void dispose() {
    _closeConnection();
    _stopServer();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {

    // force portrait mode
    SystemChrome.setPreferredOrientations([
      DeviceOrientation.portraitUp,
      DeviceOrientation.portraitDown,
    ]);

    return Scaffold(
      appBar: AppBar(
        title: Text('WebSocket Demo'),
        actions: [
          IconButton(
            icon: Icon(Icons.close),
            onPressed: _closeConnection,
          ),
        ],
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            if (!_isServerRunning)
              ElevatedButton(
                onPressed: _startServer,
                child: Text('Start WebSocket Server'),
              )
            else
              ElevatedButton(
                onPressed: _stopServer,
                child: Text('Stop WebSocket Server'),
              ),
            SizedBox(height: 10),
            if (_localIpAddress != null)
              Text('Server URL: ws://$_localIpAddress:8080'),
            SizedBox(height: 10),
            TextField(
              controller: _urlController,
              decoration: InputDecoration(labelText: 'WebSocket URL'),
              onSubmitted: (value) => _joinWebSocket(),
            ),
            SizedBox(height: 10),
            ElevatedButton(
              onPressed: _joinWebSocket,
              child: Text('Join WebSocket'),
            ),
            SizedBox(height: 10),
            Expanded(
              child: ListView.builder(
                itemCount: _messages.length,
                itemBuilder: (context, index) {
                  return ListTile(
                    title: Text(_messages[index]),
                  );
                },
              ),
            ),
            TextField(
              controller: _controller,
              decoration: InputDecoration(labelText: 'Send a message'),
              onSubmitted: (text) {
                _sendMessage(text);
                _controller.clear();
              },
            ),
          ],
        ),
      ),
    );
  }
}
