import 'package:component_library/component_library.dart';
import 'package:component_library/src/theme/spacing.dart';
import 'package:flutter/material.dart';

const _dividerThemeData = DividerThemeData(
  space: 0,
);

// If the number of properties get too big, we can start grouping them in
// classes like Flutter does with TextTheme, ButtonTheme, etc, inside ThemeData.
abstract class GolekThemeData {
  ThemeData get materialThemeData;

  double screenMargin = Spacing.mediumLarge;

  double gridSpacing = Spacing.mediumLarge;

  Color get primaryMainColor;

  Color get primaryOldColor;

  Color get primarySurfaceColor;

  Color get primaryBorderColor;

  Color get primaryHoverColor;

  Color get primaryPressedColor;

  Color get primaryFocusColor;

  Color get secondaryMainColor;

  Color get secondarySurfaceColor;

  Color get secondaryBorderColor;

  Color get secondaryHoverColor;

  Color get secondaryPressedColor;

  Color get secondaryFocusColor;

  Color get tertiaryMainColor;

  Color get tertiarySurfaceColor;

  Color get tertiaryBorderColor;

  Color get tertiaryHoverColor;

  Color get tertiaryPressedColor;

  Color get tertiaryFocusColor;

  Color get disabledColor;

  Color get neutral10Color;

  Color get neutral20Color;

  Color get neutral30Color;

  Color get neutral40Color;

  Color get neutral50Color;

  Color get neutral60Color;

  Color get neutral70Color;

  Color get neutral80Color;

  Color get neutral90Color;

  Color get neutral100Color;

  Color get dangerMainColor;

  Color get dangerSurfaceColor;

  Color get dangerBorderColor;

  Color get dangerHoverColor;

  Color get dangerPressedColor;

  Color get successMainColor;

  Color get successSurfaceColor;

  Color get successBorderColor;

  Color get successHoverColor;

  Color get successPressedColor;

  Color get warningMainColor;

  Color get warningSurfaceColor;

  Color get warningBorderColor;

  Color get warningHoverColor;

  Color get warningPressedColor;

  TextStyle textStyle = const TextStyle(
    fontFamily: 'Montserrat',
    package: 'component_library',
  );
}

class LightGolekThemeData extends GolekThemeData {
  @override
  ThemeData get materialThemeData => ThemeData(
        brightness: Brightness.light,
        primarySwatch: Colors.black.toMaterialColor(),
        dividerTheme: _dividerThemeData,
        backgroundColor: neutral10Color,
        appBarTheme: const AppBarTheme(
          backgroundColor: Colors.transparent,
          elevation: 0,
        ),
        outlinedButtonTheme: OutlinedButtonThemeData(
          style: OutlinedButton.styleFrom(
            foregroundColor: Colors.white,
            backgroundColor: primaryMainColor,
            side: const BorderSide(
              color: Colors.transparent,
            ),
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(6),
            ),
          ),
        ),
        primaryColor: primaryMainColor,
        inputDecorationTheme: InputDecorationTheme(
          errorStyle: const TextStyle(fontSize: 0, height: 1),
          border: OutlineInputBorder(
            borderRadius: BorderRadius.circular(6),
            borderSide: BorderSide(color: neutral50Color),
          ),
          disabledBorder: OutlineInputBorder(
            borderRadius: BorderRadius.circular(6),
            borderSide: BorderSide(color: neutral50Color),
          ),
          enabledBorder: OutlineInputBorder(
            borderRadius: BorderRadius.circular(6),
            borderSide: BorderSide(color: neutral50Color),
          ),
          focusedBorder: OutlineInputBorder(
            borderRadius: BorderRadius.circular(6),
            borderSide: BorderSide(
              color: primaryBorderColor,
              width: 2,
            ),
          ),
          hintStyle: textStyle.copyWith(
            fontSize: FontSize.style14,
            color: neutral70Color,
          ),
          floatingLabelBehavior: FloatingLabelBehavior.never,
        ),
        colorScheme: ColorScheme.light(
          primary: primaryMainColor, // header background color
          onSurface: secondaryMainColor, // body text color
        ),
        textButtonTheme: TextButtonThemeData(
          style: TextButton.styleFrom(
            foregroundColor: primaryMainColor, // button text color
          ),
        ),
      );

  @override
  Color get dangerBorderColor => const Color(0xffFEC4C4);

  @override
  Color get dangerHoverColor => const Color(0xffFA2020);

  @override
  Color get dangerMainColor => const Color(0xffFA2020);

  @override
  Color get dangerPressedColor => const Color(0xffE11D1D);

  @override
  Color get dangerSurfaceColor => const Color(0xffFED2D2);

  @override
  Color get disabledColor => const Color(0xffededed);

  @override
  Color get neutral10Color => Colors.white;

  @override
  Color get neutral20Color => const Color(0xffEAF2FF);

  @override
  Color get neutral30Color => const Color(0xffC6CFDD);

  @override
  Color get neutral40Color => const Color(0xffB0B8C5);

  @override
  Color get neutral50Color => const Color(0xff9AA1AC);

  @override
  Color get neutral60Color => const Color(0xff848A94);

  @override
  Color get neutral70Color => const Color(0xff6E737B);

  @override
  Color get neutral80Color => const Color(0xff585C62);

  @override
  Color get neutral90Color => const Color(0xff585C62);

  @override
  Color get neutral100Color => const Color(0xff3E3E3E);

  @override
  Color get primaryBorderColor => const Color(0xff9EF3D4);

  @override
  Color get primaryFocusColor => const Color(0xff5EEBB7).withOpacity(0.2);

  @override
  Color get primaryHoverColor => const Color(0xff4BBC92);

  @override
  Color get primaryMainColor => const Color(0xff4BBC92);

  @override
  Color get primaryOldColor => const Color(0xff5EEBB7);

  @override
  Color get primaryPressedColor => const Color(0xff388D6E);

  @override
  Color get primarySurfaceColor => const Color(0xffEFFDF8);

  @override
  Color get secondaryBorderColor => const Color(0xffFFECAA);

  @override
  Color get secondaryFocusColor => const Color.fromRGBO(255, 199, 0, 0.2);

  @override
  Color get secondaryHoverColor => const Color(0xffE6B300);

  @override
  Color get secondaryMainColor => const Color(0xff122307);

  @override
  Color get secondaryPressedColor => const Color(0xffCC9F00);

  @override
  Color get secondarySurfaceColor => const Color(0xffFFF2C3);

  @override
  Color get successBorderColor => const Color(0xffD8FFF0);

  @override
  Color get successHoverColor => const Color(0xff3DFFB5);

  @override
  Color get successMainColor => const Color(0xff8BFFD3);

  @override
  Color get successPressedColor => const Color(0xff18D48C);

  @override
  Color get successSurfaceColor => const Color(0xffECFFF8);

  @override
  Color get tertiaryBorderColor => const Color(0xffDCE6F6);

  @override
  Color get tertiaryFocusColor => const Color.fromRGBO(198, 207, 221, 0.2);

  @override
  Color get tertiaryHoverColor => const Color(0xffB0B8C5);

  @override
  Color get tertiaryMainColor => const Color(0xff1A82E4);

  @override
  Color get tertiaryPressedColor => const Color(0xff9AA1AC);

  @override
  Color get tertiarySurfaceColor => const Color(0xffF5F5F5);

  @override
  Color get warningBorderColor => const Color(0xffFFF9CF);

  @override
  Color get warningHoverColor => const Color(0xffFEE31A);

  @override
  Color get warningMainColor => const Color(0xffFFEE6E);

  @override
  Color get warningPressedColor => const Color(0xffCBB511);

  @override
  Color get warningSurfaceColor => const Color(0xffFFFCE2);
}

class DarkGolekThemeData extends GolekThemeData {
  @override
  ThemeData get materialThemeData => ThemeData(
        brightness: Brightness.dark,
        toggleableActiveColor: Colors.white,
        primarySwatch: Colors.white.toMaterialColor(),
        dividerTheme: _dividerThemeData,
      );

  @override
  // TODO: implement dangerBorderColor
  Color get dangerBorderColor => throw UnimplementedError();

  @override
  // TODO: implement dangerHoverColor
  Color get dangerHoverColor => throw UnimplementedError();

  @override
  // TODO: implement dangerMainColor
  Color get dangerMainColor => throw UnimplementedError();

  @override
  // TODO: implement dangerPressedColor
  Color get dangerPressedColor => throw UnimplementedError();

  @override
  // TODO: implement dangerSurfaceColor
  Color get dangerSurfaceColor => throw UnimplementedError();

  @override
  // TODO: implement disabledColor
  Color get disabledColor => throw UnimplementedError();

  @override
  // TODO: implement neutral100Color
  Color get neutral100Color => throw UnimplementedError();

  @override
  // TODO: implement neutral10Color
  Color get neutral10Color => throw UnimplementedError();

  @override
  // TODO: implement neutral20Color
  Color get neutral20Color => throw UnimplementedError();

  @override
  // TODO: implement neutral30Color
  Color get neutral30Color => throw UnimplementedError();

  @override
  // TODO: implement neutral40Color
  Color get neutral40Color => throw UnimplementedError();

  @override
  // TODO: implement neutral50Color
  Color get neutral50Color => throw UnimplementedError();

  @override
  // TODO: implement neutral60Color
  Color get neutral60Color => throw UnimplementedError();

  @override
  // TODO: implement neutral70Color
  Color get neutral70Color => throw UnimplementedError();

  @override
  // TODO: implement neutral80Color
  Color get neutral80Color => throw UnimplementedError();

  @override
  // TODO: implement neutral90Color
  Color get neutral90Color => throw UnimplementedError();

  @override
  // TODO: implement primaryBorderColor
  Color get primaryBorderColor => throw UnimplementedError();

  @override
  // TODO: implement primaryFocusColor
  Color get primaryFocusColor => throw UnimplementedError();

  @override
  // TODO: implement primaryHoverColor
  Color get primaryHoverColor => throw UnimplementedError();

  @override
  // TODO: implement primaryMainColor
  Color get primaryMainColor => throw UnimplementedError();

  @override
  // TODO: implement primaryOldColor
  Color get primaryOldColor => throw UnimplementedError();

  @override
  // TODO: implement primaryPressedColor
  Color get primaryPressedColor => throw UnimplementedError();

  @override
  // TODO: implement primarySurfaceColor
  Color get primarySurfaceColor => throw UnimplementedError();

  @override
  // TODO: implement secondaryBorderColor
  Color get secondaryBorderColor => throw UnimplementedError();

  @override
  // TODO: implement secondaryFocusColor
  Color get secondaryFocusColor => throw UnimplementedError();

  @override
  // TODO: implement secondaryHoverColor
  Color get secondaryHoverColor => throw UnimplementedError();

  @override
  // TODO: implement secondaryMainColor
  Color get secondaryMainColor => throw UnimplementedError();

  @override
  // TODO: implement secondaryPressedColor
  Color get secondaryPressedColor => throw UnimplementedError();

  @override
  // TODO: implement secondarySurfaceColor
  Color get secondarySurfaceColor => throw UnimplementedError();

  @override
  // TODO: implement successBorderColor
  Color get successBorderColor => throw UnimplementedError();

  @override
  // TODO: implement successHoverColor
  Color get successHoverColor => throw UnimplementedError();

  @override
  // TODO: implement successMainColor
  Color get successMainColor => throw UnimplementedError();

  @override
  // TODO: implement successPressedColor
  Color get successPressedColor => throw UnimplementedError();

  @override
  // TODO: implement successSurfaceColor
  Color get successSurfaceColor => throw UnimplementedError();

  @override
  // TODO: implement tertiaryBorderColor
  Color get tertiaryBorderColor => throw UnimplementedError();

  @override
  // TODO: implement tertiaryFocusColor
  Color get tertiaryFocusColor => throw UnimplementedError();

  @override
  // TODO: implement tertiaryHoverColor
  Color get tertiaryHoverColor => throw UnimplementedError();

  @override
  // TODO: implement tertiaryMainColor
  Color get tertiaryMainColor => throw UnimplementedError();

  @override
  // TODO: implement tertiaryPressedColor
  Color get tertiaryPressedColor => throw UnimplementedError();

  @override
  // TODO: implement tertiarySurfaceColor
  Color get tertiarySurfaceColor => throw UnimplementedError();

  @override
  // TODO: implement warningBorderColor
  Color get warningBorderColor => throw UnimplementedError();

  @override
  // TODO: implement warningHoverColor
  Color get warningHoverColor => throw UnimplementedError();

  @override
  // TODO: implement warningMainColor
  Color get warningMainColor => throw UnimplementedError();

  @override
  // TODO: implement warningPressedColor
  Color get warningPressedColor => throw UnimplementedError();

  @override
  // TODO: implement warningSurfaceColor
  Color get warningSurfaceColor => throw UnimplementedError();
}

extension on Color {
  Map<int, Color> _toSwatch() => {
        50: withOpacity(0.1),
        100: withOpacity(0.2),
        200: withOpacity(0.3),
        300: withOpacity(0.4),
        400: withOpacity(0.5),
        500: withOpacity(0.6),
        600: withOpacity(0.7),
        700: withOpacity(0.8),
        800: withOpacity(0.9),
        900: this,
      };

  MaterialColor toMaterialColor() => MaterialColor(
        value,
        _toSwatch(),
      );
}
