// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'dart:math' show min;

export 'package:dart_console/dart_console.dart';
import 'package:dart_console/dart_console.dart';

class SmartConsole extends Console {
  final ScrollbackBuffer history;
  late final List<KeyHandler> handlers;
  KeyHandler? completionHandler;

  SmartConsole({this.completionHandler})
      : history = ScrollbackBuffer(recordBlanks: false) {
    handlers = [
      BashNavigationKeyHandler(),
      BashHistoryKeyHandler(history),
      BashEditKeyHandler(),
    ];
  }

  ReadLineResult smartReadLine() {
    final buffer = LineEditBuffer();

    int promptRow = cursorPosition!.row;

    cursorPosition = Coordinate(promptRow, 0);
    drawPrompt(buffer);

    while (true) {
      final key = readKey();

      bool wasHandled = false;
      for (final handler in handlers) {
        if (handler.handleKey(buffer, key)) {
          wasHandled = true;
          break;
        }
      }
      if (completionHandler != null &&
          completionHandler!.handleKey(buffer, key)) {
        wasHandled = true;
      }

      if (!wasHandled && key.isControl) {
        switch (key.controlChar) {
          // Accept
          case ControlCharacter.enter:
            history.add(buffer.text);
            writeLine();
            return ReadLineResult(buffer.text, false, false);

          // Cancel this line.
          case ControlCharacter.ctrlC:
            return ReadLineResult('', true, false);

          // EOF
          case ControlCharacter.ctrlD:
            if (!buffer.text.isEmpty) break;
            return ReadLineResult('', true, true);

          // Ignore.
          default:
            break;
        }
      }

      cursorPosition = Coordinate(promptRow, 0);
      drawPrompt(buffer);
    }
  }

  void drawPrompt(LineEditBuffer buffer) {
    const prefix = '(hsa) ';

    final row = cursorPosition!.row;

    setForegroundColor(ConsoleColor.brightBlue);
    write(prefix);
    resetColorAttributes();
    setForegroundColor(ConsoleColor.brightGreen);

    eraseCursorToEnd();
    if (buffer.completionText.isNotEmpty) {
      write(buffer.text.substring(0, buffer.index));
      setForegroundColor(ConsoleColor.brightWhite);
      write(buffer.completionText);
      setForegroundColor(ConsoleColor.brightGreen);
      write(buffer.text.substring(buffer.index));
    } else {
      write(buffer.text);
    }

    cursorPosition = Coordinate(row, prefix.length + buffer.index);
  }
}

class ReadLineResult {
  final String text;
  final bool wasCancelled;
  final bool shouldExit;

  ReadLineResult(this.text, this.wasCancelled, this.shouldExit);
}

/// Handler of a new key stroke when editing a line.
abstract class KeyHandler {
  bool handleKey(LineEditBuffer buffer, Key key);
}

/// Handles cursor navigation.
class BashNavigationKeyHandler extends KeyHandler {
  bool handleKey(LineEditBuffer buffer, Key key) {
    if (!key.isControl) return false;

    switch (key.controlChar) {
      case ControlCharacter.arrowLeft:
      case ControlCharacter.ctrlB:
        buffer.moveLeft();
        return true;
      case ControlCharacter.arrowRight:
      case ControlCharacter.ctrlF:
        buffer.moveRight();
        return true;
      case ControlCharacter.wordLeft:
        buffer.moveWordLeft();
        return true;
      case ControlCharacter.wordRight:
        buffer.moveWordRight();
        return true;
      case ControlCharacter.home:
      case ControlCharacter.ctrlA:
        buffer.moveStart();
        return true;
      case ControlCharacter.end:
      case ControlCharacter.ctrlE:
        buffer.moveEnd();
        return true;
      default:
        return false;
    }
  }
}

/// Handles history navigation.
class BashHistoryKeyHandler extends KeyHandler {
  ScrollbackBuffer history;

  BashHistoryKeyHandler(this.history);

  bool handleKey(LineEditBuffer buffer, Key key) {
    if (!key.isControl) return false;

    switch (key.controlChar) {
      case ControlCharacter.ctrlP:
      case ControlCharacter.arrowUp:
        buffer.replaceWith(history.up(buffer.text));
        return true;
      case ControlCharacter.ctrlN:
      case ControlCharacter.arrowDown:
        final temp = history.down();
        if (temp != null) {
          buffer.replaceWith(temp);
        }
        return true;
      default:
        return false;
    }
  }
}

/// Handles text edits.
class BashEditKeyHandler extends KeyHandler {
  bool handleKey(LineEditBuffer buffer, Key key) {
    if (!key.isControl) {
      buffer.insert(key.char);
      return true;
    }

    // TODO: Add support for <alt-d> (delete word).
    switch (key.controlChar) {
      case ControlCharacter.backspace:
      case ControlCharacter.ctrlH:
        buffer.backspace();
        return true;
      case ControlCharacter.ctrlU:
        buffer.truncateLeft();
        return true;
      case ControlCharacter.ctrlK:
        buffer.truncateRight();
        return true;
      case ControlCharacter.delete:
      case ControlCharacter.ctrlD:
        final wasDeleted = buffer.delete();
        return wasDeleted;
      default:
        return false;
    }
  }
}

/// Represents the state of [Console.readLine] while editing the line.
class LineEditBuffer {
  /// The _text that was so far entered.
  String _text = '';

  /// The _index into [_text] where the editing cursor is currently being drawn.
  int _index = 0;

  /// The _text to display as inline completion.
  String completionText = '';

  LineEditBuffer();

  String get text => _text;

  int get index => _index;

  void moveWordLeft() {
    if (_index > 0) {
      final textLeftOfCursor = _text.substring(0, _index - 1);
      final lastSpace = textLeftOfCursor.lastIndexOf(' ');
      _index = lastSpace != -1 ? lastSpace + 1 : 0;
    }
  }

  void moveWordRight() {
    if (_index < _text.length) {
      final textRightOfCursor = _text.substring(_index + 1);
      final nextSpace = textRightOfCursor.indexOf(' ');
      _index = nextSpace != -1
          ? min(_index + nextSpace + 2, _text.length)
          : _text.length;
    }
  }

  void moveLeft() {
    if (_index > 0) _index--;
  }

  void moveRight() {
    if (_index < _text.length) _index++;
  }

  void moveStart() {
    _index = 0;
  }

  void moveEnd() {
    _index = _text.length;
  }

  void replaceWith(String newtext) {
    _text = newtext;
    _index = _text.length;
  }

  void truncateRight() {
    _text = _text.substring(0, _index);
  }

  void truncateLeft() {
    _text = _text.substring(_index, _text.length);
    _index = 0;
  }

  void backspace() {
    if (_index > 0) {
      _text = _text.substring(0, _index - 1) + _text.substring(_index);
      _index--;
    }
  }

  bool delete() {
    if (_index < _text.length) {
      _text = _text.substring(0, _index) + _text.substring(_index + 1);
      return true;
    }
    return false;
  }

  void insert(String chars) {
    if (_index == _text.length) {
      _text += chars;
    } else {
      _text = _text.substring(0, _index) + chars + _text.substring(_index);
    }
    _index += chars.length;
  }
}
