import 'dart:io';

import 'package:comunic/enums/post_kind.dart';
import 'package:comunic/enums/post_target.dart';
import 'package:comunic/enums/post_visibility_level.dart';
import 'package:comunic/helpers/posts_helper.dart';
import 'package:comunic/models/new_post.dart';
import 'package:comunic/ui/dialogs/input_url_dialog.dart';
import 'package:comunic/ui/dialogs/input_youtube_link_dialog.dart';
import 'package:comunic/ui/dialogs/new_survey_dialog.dart';
import 'package:comunic/utils/files_utils.dart';
import 'package:comunic/utils/intl_utils.dart';
import 'package:comunic/utils/post_utils.dart';
import 'package:comunic/utils/ui_utils.dart';
import 'package:file_picker_cross/file_picker_cross.dart';
import 'package:flutter/material.dart';

/// Widget that allows to create posts
///
/// @author Pierre HUBERT

const _ActiveButtonsColor = Colors.blue;
const _ActiveButtonsTextColor = Colors.white;
const _InactiveButtonsColor = Colors.grey;
const _InactiveButtonsTextColor = Colors.black;

class PostCreateFormWidget extends StatefulWidget {
  final PostTarget postTarget;
  final int targetID;
  final void Function() onCreated;

  const PostCreateFormWidget({
    Key key,
    @required this.postTarget,
    @required this.targetID,
    @required this.onCreated,
  })  : assert(postTarget != null),
        assert(targetID != null),
        super(key: key);

  @override
  _PostCreateFormWidgetState createState() => _PostCreateFormWidgetState();
}

class _PostCreateFormWidgetState extends State<PostCreateFormWidget> {
  // Helpers
  final PostsHelper _postHelper = PostsHelper();

  // Class members
  bool _isCreating = false;
  final TextEditingController _postTextController = TextEditingController();
  PostVisibilityLevel _postVisibilityLevel;
  File _postImage;
  String _postURL;
  List<int> _postPDF;
  DateTime _timeEnd;
  NewSurvey _postSurvey;
  String _youtubeID;

  bool get hasImage => _postImage != null;

  bool get hasURL => _postURL != null;

  bool get hasPDF => _postPDF != null;

  bool get hasTimeEnd => _timeEnd != null;

  bool get hasSurvey => _postSurvey != null;

  bool get hasYouTubeID => _youtubeID != null;

  bool get canSubmitForm =>
      !_isCreating && _postTextController.text.length > 5 ||
      postKind != PostKind.TEXT;

  PostKind get postKind {
    if (hasImage)
      return PostKind.IMAGE;
    else if (hasPDF)
      return PostKind.PDF;
    else if (hasURL)
      return PostKind.WEB_LINK;
    else if (hasTimeEnd)
      return PostKind.COUNTDOWN;
    else if (hasSurvey)
      return PostKind.SURVEY;
    else if (hasYouTubeID)
      return PostKind.YOUTUBE;
    else
      return PostKind.TEXT;
  }

  @override
  void initState() {
    super.initState();

    _resetForm();
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        // Post text content
        Padding(
          padding: const EdgeInsets.only(left: 8.0, right: 8.0),
          child: TextField(
            controller: _postTextController,
            minLines: 3,
            maxLines: 10,
            decoration: InputDecoration(hintText: tr("Create a new post...")),
            onChanged: (s) => setState(() {}),
          ),
        ),

        // Post options
        Padding(
          padding: const EdgeInsets.only(right: 16.0),
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: <Widget>[
              // Text post button
              Expanded(
                child: SingleChildScrollView(
                  scrollDirection: Axis.horizontal,
                  child: Row(
                    children: <Widget>[
                      _PostOptionWidget(
                          icon: Icons.text_format,
                          selected: postKind == PostKind.TEXT,
                          onTap: _resetPostSelection),

                      // Include image button
                      _PostOptionWidget(
                        icon: Icons.image,
                        selected: postKind == PostKind.IMAGE,
                        onTap: _pickImageForPost,
                      ),

                      // Web link
                      _PostOptionWidget(
                        icon: Icons.link,
                        selected: postKind == PostKind.WEB_LINK,
                        onTap: _pickURLForPost,
                      ),

                      // Include PDF button
                      _PostOptionWidget(
                        icon: Icons.picture_as_pdf,
                        selected: postKind == PostKind.PDF,
                        onTap: _pickPDFForPost,
                      ),

                      // Add countdown timer
                      _PostOptionWidget(
                        icon: Icons.timer,
                        selected: postKind == PostKind.COUNTDOWN,
                        onTap: _pickCountdownTime,
                      ),

                      // Add survey
                      _PostOptionWidget(
                        icon: Icons.insert_chart,
                        selected: postKind == PostKind.SURVEY,
                        onTap: _pickSurvey,
                      ),

                      // Specify YouTube video ID
                      _PostOptionWidget(
                        icon: Icons.ondemand_video,
                        selected: postKind == PostKind.YOUTUBE,
                        onTap: _pickYouTubeVideo,
                      ),
                    ],
                  ),
                ),
              ),

              Container(width: 20),

              // Post visibility level
              _PostOptionWidget(
                icon: PostVisibilityLevelsMapIcons[_postVisibilityLevel],
                selected: false,
                customColor: Colors.black,
                onTap: _changeVisibilityLevel,
              ),

              // Submit post button
              _isCreating
                  ? Container()
                  : FlatButton(
                      child: Text(tr("Send").toUpperCase()),
                      onPressed: canSubmitForm ? _submitForm : null,
                      color: _ActiveButtonsColor,
                      textColor: _ActiveButtonsTextColor,
                      disabledColor: _InactiveButtonsColor,
                      disabledTextColor: _InactiveButtonsTextColor,
                    ),
            ],
          ),
        )
      ],
    );
  }

  /// Reset the form
  void _resetForm() {
    setState(() {
      _postVisibilityLevel = widget.postTarget == PostTarget.GROUP_PAGE
          ? PostVisibilityLevel.GROUP_MEMBERS
          : PostVisibilityLevel.FRIENDS;

      _postTextController.text = "";
      _resetPostSelection();
    });
  }

  /// Change post visibility level
  Future<void> _changeVisibilityLevel() async {
    final newLevel = await showPostVisibilityPicker(
      context: context,
      initialLevel: _postVisibilityLevel,
      isGroup: widget.postTarget == PostTarget.GROUP_PAGE,
    );

    setState(() => _postVisibilityLevel = newLevel);
  }

  /// Remove all data attached to the post (image, etc...)
  void _resetPostSelection() {
    setState(() {
      _postImage = null;
      _postURL = null;
      _postPDF = null;
      _timeEnd = null;
      _postSurvey = null;
      _youtubeID = null;
    });
  }

  /// Pick an image for the new post
  Future<void> _pickImageForPost() async {
    final image = await pickImage(context);

    if (image == null) return;

    _resetPostSelection();

    setState(() {
      this._postImage = image;
    });
  }

  /// Choose a new URL for the post
  Future<void> _pickURLForPost() async {
    final url = await showInputURLDialog(
      context: context,
      title: tr("Specify URL"),
      initialURL: _postURL,
    );

    if (url == null) return;

    _resetPostSelection();

    setState(() {
      _postURL = url;
    });
  }

  /// Pick a PDF for the new post
  Future<void> _pickPDFForPost() async {
    try {
      final picker = FilePickerCross(
        type: FileTypeCross.custom,
        fileExtension: "pdf",
      );

      if (!await picker.pick()) return;

      _resetPostSelection();

      setState(() {
        this._postPDF = picker.toUint8List();
      });
    } catch (e, stack) {
      print("Pick PDF error: $e\n$stack");
      showSimpleSnack(context, tr("Could not pick a PDF!"));
    }
  }

  /// Pick countdown time
  Future<void> _pickCountdownTime() async {
    final yesterday = DateTime.now().subtract(Duration(days: 1));

    final initialDate = _timeEnd == null ? DateTime.now() : _timeEnd;

    // Pick date
    final newDate = await showDatePicker(
        context: context,
        initialDate: initialDate,
        firstDate: yesterday.isBefore(initialDate) ? yesterday : initialDate,
        lastDate: DateTime.now().add(Duration(days: 5000)));

    if (newDate == null) return;

    // Pick time
    final newTime = await showTimePicker(
      context: context,
      initialTime: TimeOfDay.fromDateTime(initialDate),
    );

    if (newTime == null) return;

    // Apply new selection
    _resetPostSelection();
    setState(() {
      _timeEnd = newDate.add(Duration(
          hours: newTime.hour - newDate.hour,
          minutes: newTime.minute - newDate.minute,
          seconds: -newDate.second));
    });
  }

  /// Pick a new survey for this post
  Future<void> _pickSurvey() async {
    final newSurvey =
        await showNewSurveyDialog(context: context, initialSurvey: _postSurvey);

    if (newSurvey == null) return;

    _resetPostSelection();
    setState(() {
      _postSurvey = newSurvey;
    });
  }

  /// Pick a new YouTube video
  Future<void> _pickYouTubeVideo() async {

    final youtubeID = await showInputYouTubeIDDialog(context, _youtubeID);

    if (youtubeID == null) return;

    _resetPostSelection();
    setState(() {
      _youtubeID = youtubeID;
    });

  }

  /// Submit new post
  Future<void> _submitForm() async {
    if (!canSubmitForm)
      showSimpleSnack(context, tr("Form can not be submitted at this point!"));

    setState(() => _isCreating = true);

    try {
      await _postHelper.createPost(NewPost(
        target: widget.postTarget,
        targetID: widget.targetID,
        visibility: _postVisibilityLevel,
        content: _postTextController.text,
        kind: postKind,
        image: _postImage,
        url: _postURL,
        pdf: _postPDF,
        timeEnd: _timeEnd,
        survey: _postSurvey,
        youtubeId: _youtubeID,
      ));
      setState(() => _isCreating = false);

      showSimpleSnack(context, tr("The post has been successfully created!"));

      this._resetForm();
      widget.onCreated();
    } catch (e) {
      setState(() => _isCreating = false);
      print("Error while creating post : " + e.toString());
      showSimpleSnack(context, tr("Could not create post !"));
    }
  }
}

/// Widget for a single post option
class _PostOptionWidget extends StatelessWidget {
  final IconData icon;
  final bool selected;
  final Color customColor;
  final void Function() onTap;

  const _PostOptionWidget(
      {Key key,
      @required this.icon,
      @required this.selected,
      @required this.onTap,
      this.customColor})
      : assert(icon != null),
        assert(selected != null),
        assert(onTap != null),
        super(key: key);

  bool get hasCustomColor => customColor != null;

  @override
  Widget build(BuildContext context) {
    return IconButton(
      icon: Icon(icon),
      onPressed: onTap,
      color: hasCustomColor
          ? customColor
          : selected ? _ActiveButtonsColor : _InactiveButtonsColor,
    );
  }
}