import 'dart:ffi';
import 'dart:io';
import 'package:ambient/firebase.dart';
import 'package:ambient/services/spotify.dart';

import 'main.dart';
import 'package:vector_math/vector_math.dart';
import 'package:image_picker/image_picker.dart';
import 'package:flutter/material.dart';
import 'package:palette_generator/palette_generator.dart';
import 'package:flutter_color_models/flutter_color_models.dart';

class StateMoodPage extends StatefulWidget {
  const StateMoodPage({super.key});

  @override
  State<StateMoodPage> createState() => MoodPage();
}

enum Moods { none, happy, sad ,angry, noble, clean, courageous, fresh, compassionn, simple, dramatic}

extension MoodsExtention on Moods {
  Color get color {
    switch (this) {
      case Moods.none:
        return Color.fromARGB(255, 75, 75, 75);
      case Moods.happy:
        return Color.fromARGB(255, 255, 255, 0);
      case Moods.sad:
        return Color.fromARGB(255, 0, 0, 255);
      case Moods.angry:
        return Color.fromARGB(255, 255, 0, 0);
      case Moods.noble:
        return Color.fromARGB(255, 127, 69, 216);
      case Moods.clean:
        return Color.fromARGB(255, 255, 255, 255);
      case Moods.courageous:
        return Color.fromARGB(255, 255, 165, 0);
      case Moods.fresh:
        return Color.fromARGB(255, 0, 255, 0);
      case Moods.compassionn:
        return Color.fromARGB(255, 255, 70, 253);
      case Moods.simple:
        return Color.fromARGB(255, 103, 64, 45);
      case Moods.dramatic:
        return Color.fromARGB(255, 0, 0, 0);
    }
  }
}

class MoodPage extends State<StateMoodPage> {
  final ImagePicker _picker = ImagePicker();
  late PaletteGenerator paletteGenerator;
  Moods? currentMood = selectedMoodAsEnum;
  String imagePath = "";

  //besorgt ein image file aus der galarie
  _getFromGallery() async {
    try {
      XFile? pickedFile = await _picker.pickImage(
        source: ImageSource.gallery,
      );
      if (pickedFile != null) {
        musicCangable = true;
        imagePath = pickedFile.path;
        setState(() {
          usesPicture = true;
          currentMoodsImage = File(imagePath);
        });
      }
    } catch (e) {
      print("could not load image: ");
      print(e);
    }
  }
  //sendet den befehl music zum passenden genre rauszusuchen
  _changeMusic() async {
    Spotify spotify = Spotify();
    //code zum musik ändern
    String hexcode = selectedMood.red.toRadixString(16) + selectedMood.green.toRadixString(16) + selectedMood.blue.toRadixString(16);
    print(hexcode);
    String genre = await changeFirebase().getGenreByHex(hexcode);
    print("genre = " + genre);
    spotify.playGenre(genre);
  }
  //vergleicht zwei farben auf ähnlichkeit
  _getColorDistance(Color c1, Color c2) {
    LabColor labC1 = LabColor.fromColor(c1);
    LabColor labC2 = LabColor.fromColor(c2);

    double distance = 0;

    print("Lightness bild: " + labC1.lightness.toDouble().toString());
    print("Lightness referenz: " + labC2.lightness.toDouble().toString());

    Vector3 v1 = Vector3(labC1.lightness.toDouble(), labC1.a.toDouble(), labC1.b.toDouble());
    Vector3 v2 = Vector3(labC2.lightness.toDouble(), labC2.a.toDouble(), labC2.b.toDouble());
    distance = v1.distanceTo(v2).toDouble();
    return distance;
  }

  _determineMoodToMatch(Color col) {
    double distance = 1000000.0;
    Moods newMood = Moods.none;
    if(musicCangable){
      for (var value in Moods.values) {
        double colorDistance = _getColorDistance(col, value.color);
        if (colorDistance < distance &&
            value != Moods.none) {
          distance = colorDistance;
          newMood = value;
        }
      }
      _updateColorPalete(col);
      selectedMoodAsEnum = newMood;
      selectedMood = newMood.color;
      _changeMusic();
      musicCangable = false;
      return newMood;
    }else{
      for (var value in Moods.values) {
        double colorDistance = _getColorDistance(selectedMood, value.color);
        if (colorDistance < distance &&
            value != Moods.none) {
          distance = colorDistance;
          newMood = value;
        }
      }
      musicCangable = false;
      return newMood;
    }
  }
  _updateColorPalete(Color col){
    if(!usesPicture){
      if(col.value != Color.fromARGB(255, 0, 0, 0).value){
        col = ligten(col, 0.2);
      }
      primaryColor = col;
    }
    backGroundColor = Color.fromARGB(col.alpha - 230, col.red, col.green, col.blue);
    primaryColor = col;
    onPrimary = darken(col, 0.5);

    Color shiftedColor = ligten(col,0.1);;

    primaryContainer = shiftedColor;
    onPrimaryContainer = darken(shiftedColor, 0.5);
  }
  //returend die liste mit den moods
  _getMoodList(){
    return Column(children: <Widget>[

          RadioListTile<Moods>(
            title: const Text(
              "Sad",
              style: TextStyle(
                  color: Color.fromARGB(255, 0, 0, 0),
              ),
            ),
            tileColor: backGroundColor,
            activeColor: primaryColor,
            value: Moods.sad,
            groupValue: currentMood,
            onChanged: (Moods? value) {
              setState(() {
                usesPicture = false;
                musicCangable = true;
                primaryColor = Moods.sad.color;
                _updateColorPalete(primaryColor);
                currentMood = value;
              });
            },
          ),
          RadioListTile<Moods>(
            title: const Text(
              "Angry",
              style: TextStyle(
                  color: Color.fromARGB(255, 0, 0, 0),
              ),
            ),
            tileColor: backGroundColor,
            activeColor: primaryColor,
            value: Moods.angry,
            groupValue: currentMood,
            onChanged: (Moods? value) {
              setState(() {
                usesPicture = false;
                musicCangable = true;
                primaryColor = Moods.angry.color;
                _updateColorPalete(primaryColor);
                currentMood = value;
              });
            },
          ),
          RadioListTile<Moods>(
            title: const Text(
              "Noble",
              style: TextStyle(
                  color: Color.fromARGB(255, 0, 0, 0),
              ),
            ),
            tileColor: backGroundColor,
            activeColor: primaryColor,
            value: Moods.noble,
            groupValue: currentMood,
            onChanged: (Moods? value) {
              setState(() {
                usesPicture = false;
                musicCangable = true;
                primaryColor = Moods.noble.color;
                _updateColorPalete(primaryColor);
                currentMood = value;
              });
            },
          ),
          RadioListTile<Moods>(
            title: const Text(
              "Clean",
              style: TextStyle(
                  color: Color.fromARGB(255, 0, 0, 0),
              ),
            ),
            tileColor: backGroundColor,
            activeColor: primaryColor,
            value: Moods.clean,
            groupValue: currentMood,
            onChanged: (Moods? value) {
              setState(() {
                usesPicture = false;
                musicCangable = true;
                primaryColor = Moods.clean.color;
                _updateColorPalete(primaryColor);
                currentMood = value;
              });
            },
          ),

      RadioListTile<Moods>(
        title: const Text(
          "Happy",
          style: TextStyle(
            color: Color.fromARGB(255, 0, 0, 0),
          ),
        ),
        tileColor: backGroundColor,
        activeColor: primaryColor,
        value: Moods.happy,
        groupValue: currentMood,
        onChanged: (Moods? value) {
          setState(() {
            usesPicture = false;
            musicCangable = true;
            primaryColor = Moods.happy.color;
            _updateColorPalete(primaryColor);
            currentMood = value;
          });
        },
      ),
          RadioListTile<Moods>(
            title: const Text(
              "Courageous",
              style: TextStyle(
                  color: Color.fromARGB(255, 0, 0, 0),
              ),
            ),
            tileColor: backGroundColor,
            activeColor: primaryColor,
            value: Moods.courageous,
            groupValue: currentMood,
            onChanged: (Moods? value) {
              setState(() {
                usesPicture = false;
                musicCangable = true;
                primaryColor = Moods.courageous.color;
                _updateColorPalete(primaryColor);
                currentMood = value;
              });
            },
          ),
          RadioListTile<Moods>(
            title: const Text(
              "Fresh",
              style: TextStyle(
                  color: Color.fromARGB(255, 0, 0, 0),
              ),
            ),
            tileColor: backGroundColor,
            activeColor: primaryColor,
            value: Moods.fresh,
            groupValue: currentMood,
            onChanged: (Moods? value) {
              setState(() {
                usesPicture = false;
                musicCangable = true;
                primaryColor = Moods.fresh.color;
                _updateColorPalete(primaryColor);
                currentMood = value;
              });
            },
          ),
          RadioListTile<Moods>(
            title: const Text(
              "Compassionn",
              style: TextStyle(
                  color: Color.fromARGB(255, 0, 0, 0),
              ),
            ),
            tileColor: backGroundColor,
            activeColor: primaryColor,
            value: Moods.compassionn,
            groupValue: currentMood,
            onChanged: (Moods? value) {
              setState(() {
                usesPicture = false;
                musicCangable = true;
                primaryColor = Moods.compassionn.color;
                _updateColorPalete(primaryColor);
                currentMood = value;
              });
            },
          ),
          RadioListTile<Moods>(
            title: const Text(
              "Simple",
              style: TextStyle(
                  color: Color.fromARGB(255, 0, 0, 0),
              ),
            ),
            tileColor: backGroundColor,
            activeColor: primaryColor,
            value: Moods.simple,
            groupValue: currentMood,
            onChanged: (Moods? value) {
              setState(() {
                usesPicture = false;
                musicCangable = true;
                primaryColor = Moods.simple.color;
                _updateColorPalete(primaryColor);
                currentMood = value;
              });
            },
          ),
          RadioListTile<Moods>(
            title: const Text(
              "Dramatic",
              style: TextStyle(
                  color: Color.fromARGB(255, 0, 0, 0),
              ),
            ),
            tileColor: backGroundColor,
            activeColor: primaryColor,
            value: Moods.dramatic,
            groupValue: currentMood,
            onChanged: (Moods? value) {
              setState(() {
                usesPicture = false;
                musicCangable = true;
                primaryColor = Moods.dramatic.color;
                _updateColorPalete(primaryColor);
                currentMood = value;
              });
            },
          ),
        ]);
  }
  // setzt das bild(falls vorhanden) in einem container ein der sich and die bildschirmgröße anpasst
  _getContainerTodisplay() {
    BoxDecoration deco = new BoxDecoration();
    var image;
    image = _getImageTodisplay();
    if (usesPicture) {
      deco = BoxDecoration(
        image: DecorationImage(
          fit: BoxFit.fitWidth,
          image: image,
        ),
      );
    } else {
      deco = BoxDecoration(
        color: primaryColor,
      );
    }
    return GestureDetector(
      onDoubleTap: (){
        _getFromGallery();
      },
      child: Container(
        width: MediaQuery.of(context).size.width,
        height: MediaQuery.of(context).size.width * (9.0 / 16.0),
        decoration: deco,
      ),
    );
  }
  //generiert ein image aus dem imagefile
  _getImageTodisplay() {
    var imageToShow;
    try {
      imageToShow = FileImage(currentMoodsImage);
      return imageToShow;
    } catch (e) {
      return null;
    }
  }
  // generiert einen paletegenerator vom aktiellen image
  Future<PaletteGenerator> _updatePaletteGenerator() async {
    if (imagePath != "") {
      paletteGenerator = await PaletteGenerator.fromImageProvider(
        _getImageTodisplay(),
      );
    }
    return paletteGenerator;
  }
  //gibt dem widged den colorindicator zur momentan generierten Primärfarbe und die Moodliste mit dem aktuell auszuwählenden Mood zurück
  _getCollorIndicatorAndMoodList() {
    return FutureBuilder<PaletteGenerator>(
        future: _updatePaletteGenerator(), // async work
        builder:
            (BuildContext context, AsyncSnapshot<PaletteGenerator> snapshot) {
          switch (snapshot.connectionState) {
            case ConnectionState.waiting:
              return const Center(child: CircularProgressIndicator());
            default:
              if (snapshot.hasError && usesPicture) {
                currentMood = _determineMoodToMatch(primaryColor);
                return Column(
                    children: <Widget>[
                      PaletteSquare( color: primaryColor),
                      _getMoodList(),
                    ]);
              } else if(snapshot.hasError) {
                return Column(
                    children: <Widget>[
                      PaletteSquare( color: primaryColor),
                      _getMoodList(),
                    ]);
              } else if (usesPicture){
                Color? colorToUse = snapshot.data!.vibrantColor?.color;
                colorToUse ??= snapshot.data!.dominantColor?.color;
                currentMood = _determineMoodToMatch(colorToUse!);
                return Column(
                  children: <Widget>[
                    PaletteSquare(color: colorToUse),
                    _getMoodList(),
                  ]);
              }else{
                return Column(
                    children: <Widget>[
                      PaletteSquare(color: primaryColor),
                      _getMoodList(),
                    ]);
              }
          }
        });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: SingleChildScrollView(
          child: Column(
            children: <Widget>[
              _getContainerTodisplay(),
              _getCollorIndicatorAndMoodList(),
              //_getMoodList(),
            ],
          ),
        ),
      ),
    );
  }
}

@immutable
class PaletteSquare extends StatelessWidget {
  const PaletteSquare({
    required this.color,
    super.key,
  });

  final Color color;

  @override
  Widget build(BuildContext context) {
    Widget square = Container(
      decoration: BoxDecoration(
          color: color, border: Border.all(width: 1.0, color: color)),
      width: MediaQuery.of(context).size.width,
      height: 40,
    );
    return square;
  }

}