#!/bin/bash
# ============================================================================
# OMARICH Connector - Installation Script for Linux
# ============================================================================
# This script installs the OMARICH Bridge for connecting GER Detect 
# and other metal detectors to omarich.codincloud.com
#
# Usage: chmod +x omarich-connector.AppImage.sh && ./omarich-connector.AppImage.sh
# ============================================================================

set -e

# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m'

echo ""
echo -e "${CYAN}╔════════════════════════════════════════════════════════════╗${NC}"
echo -e "${CYAN}║                                                            ║${NC}"
echo -e "${CYAN}║     ${GREEN}OMARICH Connector${CYAN} - Installation pour Linux           ║${NC}"
echo -e "${CYAN}║                                                            ║${NC}"
echo -e "${CYAN}║     Connectez votre GER Detect à omarich.codincloud.com   ║${NC}"
echo -e "${CYAN}║                                                            ║${NC}"
echo -e "${CYAN}╚════════════════════════════════════════════════════════════╝${NC}"
echo ""

# Installation directory
INSTALL_DIR="$HOME/.local/share/omarich-connector"
BIN_DIR="$HOME/.local/bin"
DESKTOP_DIR="$HOME/.local/share/applications"

# Check for Node.js
echo -e "${BLUE}[1/6]${NC} Vérification de Node.js..."
if ! command -v node &> /dev/null; then
    echo -e "${YELLOW}⚠️  Node.js non trouvé. Installation...${NC}"
    
    # Try different package managers
    if command -v apt-get &> /dev/null; then
        curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
        sudo apt-get install -y nodejs
    elif command -v dnf &> /dev/null; then
        sudo dnf install -y nodejs npm
    elif command -v pacman &> /dev/null; then
        sudo pacman -S --noconfirm nodejs npm
    elif command -v zypper &> /dev/null; then
        sudo zypper install -y nodejs npm
    else
        echo -e "${RED}❌ Impossible d'installer Node.js automatiquement${NC}"
        echo "   Veuillez installer Node.js manuellement: https://nodejs.org/"
        exit 1
    fi
    
    echo -e "${GREEN}✅ Node.js installé${NC}"
else
    NODE_VERSION=$(node -v)
    echo -e "${GREEN}✅ Node.js $NODE_VERSION détecté${NC}"
fi

# Add user to dialout group for serial port access
echo -e "${BLUE}[2/6]${NC} Configuration des permissions série..."
if ! groups | grep -q dialout; then
    echo -e "${YELLOW}   Ajout de l'utilisateur au groupe dialout...${NC}"
    sudo usermod -a -G dialout $USER
    echo -e "${YELLOW}   ⚠️  Vous devrez vous reconnecter pour que les permissions prennent effet${NC}"
fi
echo -e "${GREEN}✅ Permissions configurées${NC}"

# Create directories
echo -e "${BLUE}[3/6]${NC} Création des répertoires..."
mkdir -p "$INSTALL_DIR"
mkdir -p "$BIN_DIR"
mkdir -p "$DESKTOP_DIR"
cd "$INSTALL_DIR"

# Create package.json
echo -e "${BLUE}[4/6]${NC} Création des fichiers..."

cat > package.json << 'EOF'
{
  "name": "omarich-connector",
  "version": "1.0.0",
  "description": "OMARICH Bridge - Connect metal detectors to the cloud",
  "main": "bridge.js",
  "scripts": {
    "start": "node bridge.js"
  },
  "dependencies": {
    "ws": "^8.14.2",
    "serialport": "^12.0.0"
  }
}
EOF

# Create bridge.js (same as Mac version)
cat > bridge.js << 'BRIDGE_EOF'
/**
 * OMARICH Connector Bridge for Linux
 */

const { SerialPort } = require('serialport');
const WebSocket = require('ws');

const CLOUD_URL = 'wss://omarich.codincloud.com/ws/bridge';
const LOCAL_PORT = 8765;

let cloudWs = null;
let localWss = null;
let serialPort = null;
let connectedClients = new Set();
let availablePorts = [];

console.log('\n╔════════════════════════════════════════════════════════════╗');
console.log('║           OMARICH Connector Bridge v1.0.0                  ║');
console.log('╚════════════════════════════════════════════════════════════╝\n');

async function scanPorts() {
  try {
    const ports = await SerialPort.list();
    availablePorts = ports.map(p => ({
      path: p.path,
      manufacturer: p.manufacturer || 'Unknown',
      vendorId: p.vendorId,
      productId: p.productId,
      isDetector: isLikelyDetector(p)
    }));
    
    console.log('📡 Ports série disponibles:');
    if (availablePorts.length === 0) {
      console.log('   (aucun port trouvé - vérifiez que vous êtes dans le groupe dialout)');
    } else {
      availablePorts.forEach(p => {
        const indicator = p.isDetector ? '🎯' : '  ';
        console.log(`   ${indicator} ${p.path} - ${p.manufacturer}`);
      });
    }
    
    return availablePorts;
  } catch (err) {
    console.error('❌ Erreur scan ports:', err.message);
    return [];
  }
}

function isLikelyDetector(port) {
  const keywords = ['FTDI', 'Prolific', 'CH340', 'Silicon Labs', 'GER', 'OKM', 'Bluetooth', 'ttyUSB', 'ttyACM'];
  const combined = `${port.manufacturer || ''} ${port.path || ''}`.toLowerCase();
  return keywords.some(k => combined.includes(k.toLowerCase()));
}

async function connectSerial(portPath, baudRate = 9600) {
  if (serialPort && serialPort.isOpen) {
    await serialPort.close();
  }
  
  return new Promise((resolve, reject) => {
    serialPort = new SerialPort({ 
      path: portPath, 
      baudRate: baudRate,
      autoOpen: false
    });
    
    serialPort.open((err) => {
      if (err) {
        console.error(`❌ Erreur connexion ${portPath}:`, err.message);
        reject(err);
        return;
      }
      
      console.log(`✅ Connecté à ${portPath} @ ${baudRate} baud`);
      
      serialPort.on('data', (data) => {
        const dataStr = data.toString();
        console.log(`📥 Data: ${dataStr.trim()}`);
        
        const msg = JSON.stringify({
          type: 'serial_data',
          data: dataStr,
          port: portPath,
          timestamp: Date.now()
        });
        
        connectedClients.forEach(client => {
          if (client.readyState === WebSocket.OPEN) {
            client.send(msg);
          }
        });
        
        if (cloudWs && cloudWs.readyState === WebSocket.OPEN) {
          cloudWs.send(msg);
        }
      });
      
      serialPort.on('error', (err) => console.error('❌ Erreur série:', err.message));
      serialPort.on('close', () => { console.log('🔌 Port série fermé'); serialPort = null; });
      
      resolve(true);
    });
  });
}

function startLocalServer() {
  localWss = new WebSocket.Server({ port: LOCAL_PORT });
  console.log(`🌐 Serveur local démarré sur ws://localhost:${LOCAL_PORT}`);
  
  localWss.on('connection', (ws) => {
    connectedClients.add(ws);
    console.log(`👤 Client connecté (${connectedClients.size} total)`);
    
    ws.send(JSON.stringify({
      type: 'welcome',
      version: '1.0.0',
      availablePorts: availablePorts,
      connected: serialPort && serialPort.isOpen
    }));
    
    ws.on('message', async (data) => {
      try {
        const msg = JSON.parse(data);
        await handleMessage(ws, msg);
      } catch (err) {}
    });
    
    ws.on('close', () => {
      connectedClients.delete(ws);
      console.log(`👤 Client déconnecté (${connectedClients.size} restants)`);
    });
  });
}

async function handleMessage(ws, msg) {
  console.log(`📨 Message: ${msg.type}`);
  
  switch (msg.type) {
    case 'scan':
      const ports = await scanPorts();
      ws.send(JSON.stringify({ type: 'ports', ports }));
      break;
    case 'connect':
      try {
        await connectSerial(msg.port, msg.baudRate || 9600);
        ws.send(JSON.stringify({ type: 'connected', port: msg.port }));
      } catch (err) {
        ws.send(JSON.stringify({ type: 'error', error: err.message }));
      }
      break;
    case 'disconnect':
      if (serialPort && serialPort.isOpen) {
        serialPort.close();
        ws.send(JSON.stringify({ type: 'disconnected' }));
      }
      break;
    case 'send':
      if (serialPort && serialPort.isOpen) {
        serialPort.write(msg.data);
      }
      break;
    case 'status':
      ws.send(JSON.stringify({
        type: 'status',
        connected: serialPort && serialPort.isOpen,
        port: serialPort ? serialPort.path : null,
        availablePorts: availablePorts
      }));
      break;
  }
}

function connectCloud() {
  console.log('☁️  Connexion au cloud...');
  
  cloudWs = new WebSocket(CLOUD_URL);
  
  cloudWs.on('open', () => {
    console.log('☁️  Connecté au cloud OMARICH');
    cloudWs.send(JSON.stringify({
      type: 'auth',
      payload: {
        deviceInfo: {
          name: require('os').hostname(),
          platform: 'linux',
          version: '1.0.0'
        }
      }
    }));
  });
  
  cloudWs.on('message', async (data) => {
    try {
      const msg = JSON.parse(data);
      if (msg.type === 'command' && serialPort && serialPort.isOpen) {
        serialPort.write(msg.data);
      }
    } catch (err) {}
  });
  
  cloudWs.on('close', () => {
    console.log('☁️  Déconnecté du cloud, reconnexion dans 5s...');
    setTimeout(connectCloud, 5000);
  });
  
  cloudWs.on('error', (err) => console.error('☁️  Erreur cloud:', err.message));
}

async function main() {
  await scanPorts();
  startLocalServer();
  connectCloud();
  
  console.log('\n✨ OMARICH Connector prêt!');
  console.log('   Ouvrez https://omarich.codincloud.com/connector pour commencer\n');
  
  const detector = availablePorts.find(p => p.isDetector);
  if (detector) {
    console.log(`🎯 Détecteur trouvé: ${detector.path}`);
    try {
      await connectSerial(detector.path);
    } catch (err) {
      console.log('   (connexion auto échouée, connectez manuellement)');
    }
  }
}

main().catch(console.error);
BRIDGE_EOF

echo -e "${GREEN}✅ Fichiers créés${NC}"

# Install dependencies
echo -e "${BLUE}[5/6]${NC} Installation des dépendances..."
npm install --silent 2>/dev/null || npm install
echo -e "${GREEN}✅ Dépendances installées${NC}"

# Create launcher script
cat > "$BIN_DIR/omarich-connector" << EOF
#!/bin/bash
cd "$INSTALL_DIR"
node bridge.js
EOF
chmod +x "$BIN_DIR/omarich-connector"

# Create desktop entry
cat > "$DESKTOP_DIR/omarich-connector.desktop" << EOF
[Desktop Entry]
Name=OMARICH Connector
Comment=Connect your metal detector to the cloud
Exec=$BIN_DIR/omarich-connector
Terminal=true
Type=Application
Categories=Utility;
Keywords=metal;detector;GER;OKM;
EOF

echo -e "${BLUE}[6/6]${NC} Configuration terminée!"

echo ""
echo -e "${GREEN}╔════════════════════════════════════════════════════════════╗${NC}"
echo -e "${GREEN}║                                                            ║${NC}"
echo -e "${GREEN}║     ✅ Installation terminée avec succès!                  ║${NC}"
echo -e "${GREEN}║                                                            ║${NC}"
echo -e "${GREEN}╚════════════════════════════════════════════════════════════╝${NC}"
echo ""
echo -e "📂 Installé dans: ${CYAN}$INSTALL_DIR${NC}"
echo -e "🚀 Commande: ${CYAN}omarich-connector${NC}"
echo ""
echo -e "${YELLOW}Pour démarrer OMARICH Connector:${NC}"
echo -e "   Exécutez: ${CYAN}omarich-connector${NC}"
echo -e "   Ou cherchez 'OMARICH Connector' dans votre menu d'applications"
echo ""

# Check if ~/.local/bin is in PATH
if [[ ":$PATH:" != *":$HOME/.local/bin:"* ]]; then
    echo -e "${YELLOW}⚠️  Ajoutez ~/.local/bin à votre PATH:${NC}"
    echo -e "   ${CYAN}echo 'export PATH=\"\$HOME/.local/bin:\$PATH\"' >> ~/.bashrc${NC}"
    echo -e "   ${CYAN}source ~/.bashrc${NC}"
    echo ""
fi

echo -e "${BLUE}Voulez-vous démarrer OMARICH Connector maintenant? [O/n]${NC}"
read -r response
if [[ "$response" != "n" && "$response" != "N" ]]; then
    echo ""
    node bridge.js
fi
