content: import 'package:flex_color_scheme/flex_color_scheme.dart';
  import 'package:flutter/material.dart';
  
  /// A [ThemeExtension] for code highlight color properties used by code viewer.
  class CodeTheme extends ThemeExtension<CodeTheme> {
    const CodeTheme({
      this.baseColor,
      this.numberColor,
      this.commentColor,
      this.keywordColor,
      this.stringColor,
      this.punctuationColor,
      this.classColor,
      this.constantColor,
    });
    final Color? baseColor;
    final Color? numberColor;
    final Color? commentColor;
    final Color? keywordColor;
    final Color? stringColor;
    final Color? punctuationColor;
    final Color? classColor;
    final Color? constantColor;
  
    /// Must override the copyWith method.
    @override
    CodeTheme copyWith({
      Color? baseColor,
      Color? numberColor,
      Color? commentColor,
      Color? keywordColor,
      Color? stringColor,
      Color? punctuationColor,
      Color? classColor,
      Color? constantColor,
    }) =>
        CodeTheme(
          baseColor: baseColor ?? this.baseColor,
          numberColor: numberColor ?? this.numberColor,
          commentColor: commentColor ?? this.commentColor,
          keywordColor: keywordColor ?? this.keywordColor,
          stringColor: stringColor ?? this.stringColor,
          punctuationColor: punctuationColor ?? this.punctuationColor,
          classColor: classColor ?? this.classColor,
          constantColor: constantColor ?? this.constantColor,
        );
  
    /// Must override the lerp method.
    @override
    CodeTheme lerp(ThemeExtension<CodeTheme>? other, double t) {
      if (other is! CodeTheme) {
        return this;
      }
      return CodeTheme(
        baseColor: Color.lerp(baseColor, other.baseColor, t),
        numberColor: Color.lerp(numberColor, other.numberColor, t),
        commentColor: Color.lerp(commentColor, other.commentColor, t),
        keywordColor: Color.lerp(keywordColor, other.keywordColor, t),
        stringColor: Color.lerp(stringColor, other.stringColor, t),
        punctuationColor: Color.lerp(punctuationColor, other.punctuationColor, t),
        classColor: Color.lerp(classColor, other.classColor, t),
        constantColor: Color.lerp(constantColor, other.constantColor, t),
      );
    }
  
    /// Code view theme colors for light mode.
    static const CodeTheme light = CodeTheme(
      baseColor: Color(0xFF092249),
      numberColor: Color(0xFF1565C0),
      commentColor: Color(0xFF446736),
      keywordColor: Color(0xFF9C27B0),
      stringColor: Color(0xFF43A047),
      punctuationColor: Color(0xFF081936),
      classColor: Color(0xFF6607C5),
      constantColor: Color(0xFF795548),
    );
  
    /// Code view theme colors for dark mode.
    static const CodeTheme dark = CodeTheme(
      baseColor: Color(0xFFEEEED6),
      numberColor: Color(0xFFB4CDA8),
      commentColor: Color(0xFF90C07A),
      keywordColor: Color(0xFF5BAAE8),
      stringColor: Color(0xFFD3A384),
      punctuationColor: Color(0xFFEAE9D4),
      classColor: Color(0xFF39C8B0),
      constantColor: Color(0xFFB9A1DC),
    );
  
    /// A harmonized code view color theme, based on [brightness] where colors
    /// are harmonized towards a given [sourceColor].
    // ignore: sort_constructors_first
    factory CodeTheme.harmonized(Color sourceColor, Brightness brightness) {
      final int sourceColorValue = sourceColor.value32bit;
  
      // Fallback color value that can be used for all colors in both modes.
      // This use case should never happen when CodeTheme is setup correctly.
      const int fallbackValue = 0xFF1565C0; // Bright dark blue
  
      // Use the code theme for target brightness.
      final CodeTheme codeTheme = brightness == Brightness.light ? light : dark;
  
      // MaterialColorUtilities Blend function is used to harmonize each color
      // towards the source color hue. This way the code view text will fit better
      // with the overall ColorScheme. This also works well if the source color
      // for the ColorScheme was extracted from OS theme colors or a device
      // wallpaper, or any image and then created with ColorScheme.fromSeed.
      return CodeTheme(
        baseColor: Color(
          Blend.harmonize(
            // As used used in this app we could bang the color, instead of using
            // a fallback, but this is safer generally.
            codeTheme.baseColor?.value32bit ?? fallbackValue,
            sourceColorValue,
          ),
        ),
        numberColor: Color(
          Blend.harmonize(
            codeTheme.numberColor?.value32bit ?? fallbackValue,
            sourceColorValue,
          ),
        ),
        commentColor: Color(
          Blend.harmonize(
            codeTheme.commentColor?.value32bit ?? fallbackValue,
            sourceColorValue,
          ),
        ),
        keywordColor: Color(
          Blend.harmonize(
            codeTheme.keywordColor?.value32bit ?? fallbackValue,
            sourceColorValue,
          ),
        ),
        stringColor: Color(
          Blend.harmonize(
            codeTheme.stringColor?.value32bit ?? fallbackValue,
            sourceColorValue,
          ),
        ),
        punctuationColor: Color(
          Blend.harmonize(
            codeTheme.punctuationColor?.value32bit ?? fallbackValue,
            sourceColorValue,
          ),
        ),
        classColor: Color(
          Blend.harmonize(
            codeTheme.classColor?.value32bit ?? fallbackValue,
            sourceColorValue,
          ),
        ),
        constantColor: Color(
          Blend.harmonize(
            codeTheme.constantColor?.value32bit ?? fallbackValue,
            sourceColorValue,
          ),
        ),
      );
    }
  }
  