// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

extension StringExtension on String {
  static final RegExp _defaultMatcher = RegExp(r'\s+|-+|_+|\.+');

  Map<String, String> get syntaxes => {
        'camel_case': camel(),
        'constant_case': constant(),
        'dot_case': dot(),
        'header_case': header(),
        'lower_case': lower(),
        'pascal_case': pascal(),
        'param_case': param(),
        'sentence_case': sentence(),
        'title_case': title(),
        'upper_case': upper(),
        'snake_case': snake(),
        'mustache_case': mustache(),
        'path_case': path(),
      };

  /// ```dart
  /// print('abcd'.capitalize()) // Abcd
  /// print('Abcd'.capitalize()) // Abcd
  /// ```
  String capitalize() {
    switch (length) {
      case 0:
        return this;
      case 1:
        return toUpperCase();
      default:
        return substring(0, 1).toUpperCase() + substring(1);
    }
  }

  /// ```dart
  /// print('abcd'.decapitalize()) // abcd
  /// print('Abcd'.decapitalize()) // abcd
  /// ```
  String decapitalize() {
    switch (length) {
      case 0:
        return this;
      case 1:
        return toLowerCase();
      default:
        return substring(0, 1).toLowerCase() + substring(1);
    }
  }

  /// ```dart
  /// print('Hello-world'.camel()) // helloWorld
  /// print('hello_World'.camel()) // helloWorld
  /// print('Hello World'.camel()) // helloWorld
  /// print('helloWorld'.camel()) // helloWorld
  /// print('long   space'.camel()) // longSpace
  /// ```
  String camel() {
    if (length > 0) {
      return pascal().decapitalize();
    } else {
      return this;
    }
  }

  /// ```dart
  /// print('Hello World'.pascal()) // HelloWorld
  /// print('helloWorld'.pascal()) // HelloWorld
  /// print('long   space'.pascal()) // LongSpace
  /// ```
  String pascal() {
    switch (length) {
      case 0:
        return this;
      case 1:
        return toUpperCase();
      default:
        return splitMapJoin(
          _defaultMatcher,
          onMatch: (m) => '',
          onNonMatch: (n) => n.capitalize(),
        );
    }
  }

  /// ```dart
  /// print('Hello World'.constant()) // HELLO_WORLD
  /// print('helloWorld'.constant()) // HELLO_WORLD
  /// print('long   space'.constant()) // LONG_SPACE
  /// ```
  String constant() {
    switch (length) {
      case 0:
        return this;
      case 1:
        return toUpperCase();
      default:
        return splitMapJoin(
          RegExp('[A-Z]'),
          onMatch: (m) => ' ${m[0]}',
          onNonMatch: (n) => n,
        ).trim().splitMapJoin(
              _defaultMatcher,
              onMatch: (m) => '_',
              onNonMatch: (n) => n.toUpperCase(),
            );
    }
  }

  /// ```dart
  /// print('Hello World'.dot()) // hello.world
  /// print('helloWorld'.dot()) // hello.world
  /// print('long   space'.dot()) // long.space
  /// ```
  String dot() {
    switch (length) {
      case 0:
        return this;
      case 1:
        return toLowerCase();
      default:
        return splitMapJoin(
          RegExp('[A-Z]'),
          onMatch: (m) => ' ${m[0]}',
          onNonMatch: (n) => n,
        ).trim().splitMapJoin(
              _defaultMatcher,
              onMatch: (m) => '.',
              onNonMatch: (n) => n.toLowerCase(),
            );
    }
  }

  /// ```dart
  /// print('Hello World'.header()) // Hello-World
  /// print('helloWorld'.header()) // Hello-World
  /// ```
  String header() {
    switch (length) {
      case 0:
        return this;
      case 1:
        return toUpperCase();
      default:
        return splitMapJoin(
          RegExp('[A-Z]'),
          onMatch: (m) => ' ${m[0]}',
          onNonMatch: (n) => n.toLowerCase(),
        ).trim().splitMapJoin(
              _defaultMatcher,
              onMatch: (m) => '-',
              onNonMatch: (n) => n.capitalize(),
            );
    }
  }

  /// ```dart
  /// print('Hello World'.lower()) // hello world
  /// print('helloWorld'.lower()) // hello world
  /// ```
  String lower() {
    switch (length) {
      case 0:
        return this;
      case 1:
        return toLowerCase();
      default:
        return splitMapJoin(
          RegExp('[A-Z]'),
          onMatch: (m) => ' ${m[0]}',
          onNonMatch: (n) => n,
        ).trim().splitMapJoin(
              _defaultMatcher,
              onMatch: (m) => ' ',
              onNonMatch: (n) => n.toLowerCase(),
            );
    }
  }

  /// ```dart
  /// print('Hello World'.param()) // hello-world
  /// print('helloWorld'.param()) // hello-world
  /// print('long   space'.param()) // long-space
  /// ```
  String param() {
    switch (length) {
      case 0:
        return this;
      case 1:
        return toLowerCase();
      default:
        return splitMapJoin(
          RegExp('[A-Z]'),
          onMatch: (m) => ' ${m[0]}',
          onNonMatch: (n) => n,
        ).trim().splitMapJoin(
              _defaultMatcher,
              onMatch: (m) => '-',
              onNonMatch: (n) => n.toLowerCase(),
            );
    }
  }

  /// ```dart
  /// print('Hello World'.path()) // hello/world
  /// print('helloWorld'.path()) // hello/world
  /// print('long   space'.path()) // long/space
  /// ```
  String path() {
    switch (length) {
      case 0:
        return this;
      case 1:
        return toLowerCase();
      default:
        return splitMapJoin(
          RegExp('[A-Z]'),
          onMatch: (m) => ' ${m[0]}',
          onNonMatch: (n) => n,
        ).trim().splitMapJoin(
              _defaultMatcher,
              onMatch: (m) => '/',
              onNonMatch: (n) => n.toLowerCase(),
            );
    }
  }

  /// ```dart
  /// print('Hello World'.upper()) // HELLO WORLD
  /// print('helloWorld'.upper()) // HELLO WORLD
  /// ```
  String upper() {
    switch (length) {
      case 0:
        return this;
      case 1:
        return toUpperCase();
      default:
        return splitMapJoin(
          RegExp('[A-Z]'),
          onMatch: (m) => ' ${m[0]}',
          onNonMatch: (n) => n,
        ).trim().splitMapJoin(
              _defaultMatcher,
              onMatch: (m) => ' ',
              onNonMatch: (n) => n.toUpperCase(),
            );
    }
  }

  /// ```dart
  /// print('Hello World'.snake()) // hello_world
  /// print('helloWorld'.snake()) // hello_world
  /// print('long   space'.snake()) // long_space
  /// ```
  String snake() {
    switch (length) {
      case 0:
        return this;
      case 1:
        return toLowerCase();
      default:
        return splitMapJoin(
          RegExp('[A-Z]'),
          onMatch: (m) => ' ${m[0]}',
          onNonMatch: (n) => n,
        ).trim().splitMapJoin(
              _defaultMatcher,
              onMatch: (m) => '_',
              onNonMatch: (n) => n.toLowerCase(),
            );
    }
  }

  /// ```dart
  /// print('Hello World'.sentence()) // Hello world
  /// print('helloWorld'.sentence()) // Hello world
  /// ```
  String sentence() => lower().capitalize();

  /// ```dart
  /// print('Hello World'.title()) // Hello World
  /// print('helloWorld'.title()) // Hello World
  /// ```
  String title() => header().splitMapJoin(
        _defaultMatcher,
        onMatch: (m) => ' ',
        onNonMatch: (n) => n,
      );

  /// ```dart
  /// print('Hello World'.mustache()) // {{ Hello World }}
  /// print('helloWorld'.mustache()) // {{ Hello World }}
  /// ```
  String mustache() => '{{ ${title()} }}';
}
