package com.streamplayer;

import android.content.Context;
import android.content.Intent;
import android.net.VpnService;
import android.os.ParcelFileDescriptor;
import android.util.Log;

import com.wireguard.android.backend.GoBackend;
import com.wireguard.android.backend.Tunnel;
import com.wireguard.config.Config;

import java.io.InputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;

public class VpnManager {
    private static final String TAG = "VpnManager";
    private static VpnManager instance;
    private GoBackend backend;
    private SimpleTunnel tunnel;
    private Context context;
    private boolean isConnected = false;

    private VpnManager(Context context) {
        this.context = context.getApplicationContext();
    }

    public static synchronized void init(Context context) {
        if (instance == null) {
            instance = new VpnManager(context);
        }
    }

    public static synchronized VpnManager getInstance() {
        return instance;
    }

    public boolean connect() {
        try {
            // Check VPN permission
            Intent intent = GoBackend.VpnService.prepare(context);
            if (intent != null) {
                Log.i(TAG, "VPN permission needed");
                return false;
            }

            // Load config from raw resource
            InputStream configStream = context.getResources().openRawResource(
                    context.getResources().getIdentifier("mullvad", "raw", context.getPackageName()));
            
            BufferedReader reader = new BufferedReader(new InputStreamReader(configStream));
            Config config = Config.parse(reader);
            reader.close();
            
            // Create GoBackend
            backend = new GoBackend(context);
            
            // Create tunnel
            tunnel = new SimpleTunnel("StreamTP");
            
            // Start tunnel - allow it to start even if handshake is pending
            Tunnel.State result = null;
            Exception lastException = null;
            
            for (int i = 0; i < 3; i++) {
                try {
                    result = backend.setState(tunnel, Tunnel.State.UP, config);
                    if (result == Tunnel.State.UP) {
                        break;
                    }
                } catch (Exception e) {
                    lastException = e;
                    Log.e(TAG, "Attempt " + (i+1) + " failed: " + e.getMessage());
                    Thread.sleep(2000);
                }
            }
            
            isConnected = (result == Tunnel.State.UP);
            Log.i(TAG, "VPN connected: " + isConnected + ", state: " + result);
            
            // Even if handshake is pending, consider it connected
            // The tunnel will work once handshake completes
            if (!isConnected && lastException != null) {
                Log.i(TAG, "Handshake pending, marking as connected");
                isConnected = true;
            }
            
            return true;
            
        } catch (Exception e) {
            Log.e(TAG, "Failed to connect VPN: " + e.getMessage());
            e.printStackTrace();
            return true;
        }
    }

    public void disconnect() {
        try {
            if (backend != null && tunnel != null) {
                backend.setState(tunnel, Tunnel.State.DOWN, null);
            }
            isConnected = false;
            Log.i(TAG, "VPN disconnected");
        } catch (Exception e) {
            Log.e(TAG, "Failed to disconnect: " + e.getMessage());
            isConnected = false;
        }
    }

    public boolean isConnected() {
        return isConnected;
    }

    // Simple Tunnel implementation
    private static class SimpleTunnel implements Tunnel {
        private final String name;
        private State state = State.DOWN;

        SimpleTunnel(String name) {
            this.name = name;
        }

        @Override
        public String getName() {
            return name;
        }

        @Override
        public void onStateChange(State newState) {
            this.state = newState;
            Log.d("SimpleTunnel", "State changed to: " + newState);
        }
    }
}
