require "compiler/crystal/syntax"
require "./lsp/protocol"
require "./lsp/json_rpc"
require "./lsp/text_document"
require "./lsp/server"
require "./crystal/parser"
require "./crystal/semantic_analyzer"
require "./crystal/psi/psi_file"
require "./lsp/providers"
require "./cli/main"

module Lattice
  VERSION = "0.8.9"

  # Uppercase alias so specs and external callers can use `Lattice::PSI::File`
  # as well as the canonical `Lattice::Psi::PsiFile`.
  module PSI
    File = Lattice::Psi::PsiFile
  end
end

if PROGRAM_NAME.includes?("lattice")
  # Any recognised sub-command routes to the CLI dispatcher.
  cli_commands = %w[check doctor init clear-cache check-update help fmt stats list-symbols]
  first_arg = ARGV.first? || ""

  if cli_commands.includes?(first_arg) ||
     first_arg.in?("--version", "-v", "--help", "-h")
    Lattice::CLI.dispatch(ARGV.to_a)
  else
    # Default: start the LSP server.
    strict_mode = ARGV.includes?("--strict")
    STDERR.puts "Strict type checking enabled" if strict_mode

    begin
      server = LSP::Server.new
      server.enable_strict_mode if strict_mode
      server.run
    rescue exception
      STDERR.puts "Server crashed: #{exception.message}"
      STDERR.flush
    end
  end
else
  STDERR.puts "Rename the executable to 'lattice'."
end
