// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:async';
import 'dart:io' as io;

import 'package:fidl/fidl.dart';
import 'package:fidl_fuchsia_media/fidl.dart' as media;
import 'package:fidl_fuchsia_media_playback/fidl.dart' as playback;
import 'package:fidl_fuchsia_modular/fidl.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:fuchsia/fuchsia.dart';
import 'package:lib.app.dart/app.dart';
import 'package:lib.mediaplayer.flutter/media_player.dart';
import 'package:lib.mediaplayer.flutter/media_player_controller.dart';

import 'asset.dart';
import 'config.dart';

final StartupContext _context = new StartupContext.fromStartupInfo();
final MediaPlayerController _controller =
    new MediaPlayerController(_context.environmentServices);

ModuleImpl _module = new ModuleImpl();

void _log(String msg) {
  print('[mediaplayer_flutter Module] $msg');
}

/// An implementation of the [Lifecycle] interface, which controls the lifetime
/// of the module.
class ModuleImpl implements Lifecycle {
  final LifecycleBinding _lifecycleBinding = new LifecycleBinding();

  /// Binds an [InterfaceRequest] for a [Lifecycle] interface to this object.
  void bindLifecycle(InterfaceRequest<Lifecycle> request) {
    _lifecycleBinding.bind(this, request);
  }

  /// Implementation of Lifecycle.Terminate method.
  @override
  void terminate() {
    _log('ModuleImpl::Terminate call');
    _lifecycleBinding.close();
    exit(0);
  }
}

const List<String> _configFileNames = const <String>[
  '/data/mediaplayer_flutter.config',
  '/pkg/data/mediaplayer_flutter.config',
];

List<Asset> _assets = <Asset>[];
Asset _assetToPlay;
Asset _leafAssetToPlay;
int _playlistIndex;

Future<Null> _readConfig() async {
  for (String fileName in _configFileNames) {
    try {
      _assets = await readConfig(fileName);
      return;
      // ignore: avoid_catching_errors
    } on ArgumentError {
      // File doesn't exist. Continue.
    } on FormatException catch (e) {
      print('Failed to parse config $fileName: $e');
      io.exit(0);
      return;
    }
  }

  print('No config file found');
  io.exit(0);
}

/// Plays the specified asset.
void _play(Asset asset) {
  assert(asset != null);

  _assetToPlay = asset;
  _playlistIndex = 0;

  if (_assetToPlay.children != null) {
    assert(_assetToPlay.children.isNotEmpty);
    _playLeafAsset(_assetToPlay.children[0]);
  } else {
    _playLeafAsset(_assetToPlay);
  }
}

/// If [_leafAssetToPlay] is looped, this method seeks to the beginning of the
/// asset and returns true. If [_assetToPlay] is a playlist and hasn't been
/// played through (or is looped), this method plays the next asset in
/// [_assetToPlay] and returns true. Returns false otherwise.
bool _playNext() {
  if (_leafAssetToPlay.loop) {
    // Looping leaf asset. Seek to the beginning.
    _controller.seek(Duration.zero);
    return true;
  }

  if (_assetToPlay == null || _assetToPlay.children == null) {
    return false;
  }

  if (_assetToPlay.children.length <= ++_playlistIndex) {
    if (!_assetToPlay.loop) {
      return false;
    }

    // Looping playlist. Start over.
    _playlistIndex = 0;
  }

  _playLeafAsset(_assetToPlay.children[_playlistIndex]);

  return true;
}

void _playLeafAsset(Asset asset) {
  assert(asset.type != AssetType.playlist);

  _leafAssetToPlay = asset;

  if (_controller.problem?.type == playback.problemConnectionFailed) {
    _controller.close();
  }

  _controller
    ..open(_leafAssetToPlay.uri)
    ..play();
}

/// Screen for asset playback.
class _PlaybackScreen extends StatefulWidget {
  const _PlaybackScreen({Key key}) : super(key: key);

  @override
  _PlaybackScreenState createState() => new _PlaybackScreenState();
}

class _PlaybackScreenState extends State<_PlaybackScreen> {
  @override
  void initState() {
    _controller.addListener(_handleControllerChanged);
    super.initState();
  }

  @override
  void dispose() {
    _controller.removeListener(_handleControllerChanged);
    super.dispose();
  }

  /// Handles change notifications from the controller.
  void _handleControllerChanged() {
    setState(() {
      if (_controller.ended) {
        _playNext();
      }
    });
  }

  /// Adds a label to list [to] if [label] isn't null.
  void _addLabel(String label, Color color, double fontSize, List<Widget> to) {
    if (label == null) {
      return;
    }

    to.add(new Container(
      margin: const EdgeInsets.only(left: 10.0),
      child: new Text(
        label,
        style: new TextStyle(color: color, fontSize: fontSize),
      ),
    ));
  }

  /// Adds a problem description to list [to] if there is a problem.
  void _addProblem(List<Widget> to) {
    playback.Problem problem = _controller.problem;
    if (problem != null) {
      String text;

      if (problem.details != null && problem.details.isNotEmpty) {
        text = problem.details;
      } else {
        switch (problem.type) {
          case playback.problemInternal:
            text = 'Internal error';
            break;
          case playback.problemAssetNotFound:
            text = 'The requested content was not found';
            break;
          case playback.problemContainerNotSupported:
            text = 'The requested content uses an unsupported container format';
            break;
          case playback.problemAudioEncodingNotSupported:
            text = 'The requested content uses an unsupported audio encoding';
            break;
          case playback.problemVideoEncodingNotSupported:
            text = 'The requested content uses an unsupported video encoding';
            break;
          case playback.problemConnectionFailed:
            text = 'Connection to player failed';
            break;
          default:
            text = 'Unrecognized problem type ${problem.type}';
            break;
        }
      }

      _addLabel(text, Colors.white, 20.0, to);

      if (_leafAssetToPlay != null && _leafAssetToPlay.uri != null) {
        _addLabel(_leafAssetToPlay.uri.toString(), Colors.grey[800], 15.0, to);
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    List<Widget> columnChildren = <Widget>[
      new MediaPlayer(_controller),
    ];

    Map<String, String> metadata = _controller.metadata;
    if (metadata != null) {
      _addLabel(
          metadata[media.metadataLabelTitle] ??
              _leafAssetToPlay.title ??
              '(untitled)',
          Colors.white,
          20.0,
          columnChildren);
      _addLabel(
          metadata[media.metadataLabelArtist] ?? _leafAssetToPlay.artist,
          Colors.grey[600],
          15.0,
          columnChildren);
      _addLabel(
          metadata[media.metadataLabelAlbum] ?? _leafAssetToPlay.album,
          Colors.grey[800],
          15.0,
          columnChildren);
    }

    _addProblem(columnChildren);

    return new Material(
      color: Colors.black,
      child: new Stack(
        children: <Widget>[
          new Positioned(
            left: 0.0,
            right: 0.0,
            top: 0.0,
            child: new Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: columnChildren,
            ),
          ),
          new Positioned(
            right: 0.0,
            top: 0.0,
            child: new Offstage(
              offstage: !_controller.shouldShowControlOverlay,
              child: new PhysicalModel(
                elevation: 2.0,
                color: Colors.transparent,
                borderRadius: new BorderRadius.circular(60.0),
                child: new IconButton(
                  icon: new Icon(
                      _assets.length == 1 ? Icons.close : Icons.arrow_back),
                  iconSize: 60.0,
                  onPressed: () {
                    if (_assets.length == 1) {
                      io.exit(0);
                      return;
                    }

                    _controller.pause();
                    Navigator.of(context).pop();
                  },
                  color: Colors.white,
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

/// Screen for asset selection
class _ChooserScreen extends StatefulWidget {
  const _ChooserScreen({Key key}) : super(key: key);

  @override
  _ChooserScreenState createState() => new _ChooserScreenState();
}

class _ChooserScreenState extends State<_ChooserScreen> {
  Widget _buildChooseButton(Asset asset) {
    IconData iconData;

    switch (asset.type) {
      case AssetType.movie:
        iconData = Icons.movie;
        break;
      case AssetType.song:
        iconData = Icons.music_note;
        break;
      case AssetType.playlist:
        iconData = Icons.playlist_play;
        break;
    }

    return new RaisedButton(
      onPressed: () {
        _play(asset);
        Navigator.of(context).pushNamed('/play');
      },
      color: Colors.black,
      child: new Row(
        children: <Widget>[
          new Icon(
            iconData,
            size: 60.0,
            color: Colors.grey[200],
          ),
          new Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              new Text(
                asset.title ?? '(no title)',
                style: new TextStyle(color: Colors.grey[200], fontSize: 18.0),
              ),
              new Text(
                asset.artist ?? '',
                style: new TextStyle(color: Colors.grey[600], fontSize: 13.0),
              ),
              new Text(
                asset.album ?? '',
                style: new TextStyle(color: Colors.grey[800], fontSize: 13.0),
              ),
            ],
          ),
        ],
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return new Material(
      color: Colors.black,
      child: new Stack(
        children: <Widget>[
          new ListView(
            itemExtent: 75.0,
            children: _assets.map(_buildChooseButton).toList(),
          ),
          new Positioned(
            right: 0.0,
            top: 0.0,
            child: new PhysicalModel(
              elevation: 2.0,
              color: Colors.transparent,
              child: new IconButton(
                icon: const Icon(Icons.close),
                iconSize: 60.0,
                onPressed: () {
                  io.exit(0);
                },
                color: Colors.white,
              ),
            ),
          ),
        ],
      ),
    );
  }
}

Future<Null> main() async {
  _log('Module started');

  /// Add [ModuleImpl] to this application's outgoing ServiceProvider.
  _context.outgoingServices.addServiceForName(
    (InterfaceRequest<Lifecycle> request) {
      _module.bindLifecycle(request);
    },
    Lifecycle.$serviceName,
  );

  await _readConfig();

  if (_assets.isEmpty) {
    print('no assets configured');
    return;
  }

  if (_assets.length == 1) {
    _play(_assets[0]);
  }

  runApp(new MaterialApp(
    title: 'Media Player',
    home:
        _assets.length == 1 ? const _PlaybackScreen() : const _ChooserScreen(),
    routes: <String, WidgetBuilder>{
      '/play': (BuildContext context) => const _PlaybackScreen()
    },
    theme: new ThemeData(primarySwatch: Colors.blue),
    debugShowCheckedModeBanner: false,
  ));
}
