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

#ifndef MEDIA_MIDI_MIDI_MANAGER_ALSA_H_
#define MEDIA_MIDI_MIDI_MANAGER_ALSA_H_

#include <alsa/asoundlib.h>
#include <stdint.h>

#include <map>
#include <memory>
#include <unordered_map>
#include <utility>
#include <vector>

#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/synchronization/lock.h"
#include "base/thread_annotations.h"
#include "base/threading/thread.h"
#include "base/values.h"
#include "device/udev_linux/scoped_udev.h"
#include "media/midi/midi_export.h"
#include "media/midi/midi_manager.h"

namespace midi {

class MIDI_EXPORT MidiManagerAlsa final : public MidiManager {
 public:
  explicit MidiManagerAlsa(MidiService* service);
  ~MidiManagerAlsa() override;

  // MidiManager implementation.
  void StartInitialization() override;
  void DispatchSendMidiData(MidiManagerClient* client,
                            uint32_t port_index,
                            const std::vector<uint8_t>& data,
                            base::TimeTicks timestamp) override;

 private:
  friend class MidiManagerAlsaTest;
  FRIEND_TEST_ALL_PREFIXES(MidiManagerAlsaTest, ExtractManufacturer);
  FRIEND_TEST_ALL_PREFIXES(MidiManagerAlsaTest, ToMidiPortState);

  class AlsaCard;
  using AlsaCardMap = std::map<int, std::unique_ptr<AlsaCard>>;

  class MidiPort {
   public:
    enum class Type { kInput, kOutput };

    // The Id class is used to keep the multiple strings separate
    // but compare them all together for equality purposes.
    // The individual strings that make up the Id can theoretically contain
    // arbitrary characters, so unfortunately there is no simple way to
    // concatenate them into a single string.
    class Id final {
     public:
      Id();
      Id(const std::string& bus,
         const std::string& vendor_id,
         const std::string& model_id,
         const std::string& usb_interface_num,
         const std::string& serial);
      Id(const Id&);
      ~Id();
      bool operator==(const Id&) const;
      bool empty() const;

      std::string bus() const { return bus_; }
      std::string vendor_id() const { return vendor_id_; }
      std::string model_id() const { return model_id_; }
      std::string usb_interface_num() const { return usb_interface_num_; }
      std::string serial() const { return serial_; }

     private:
      std::string bus_;
      std::string vendor_id_;
      std::string model_id_;
      std::string usb_interface_num_;
      std::string serial_;
    };

    MidiPort(const std::string& path,
             const Id& id,
             int client_id,
             int port_id,
             int midi_device,
             const std::string& client_name,
             const std::string& port_name,
             const std::string& manufacturer,
             const std::string& version,
             Type type);
    ~MidiPort();

    // Gets a Value representation of this object, suitable for serialization.
    std::unique_ptr<base::Value> Value() const;

    // Gets a string version of Value in JSON format.
    std::string JSONValue() const;

    // Gets an opaque identifier for this object, suitable for using as the id
    // field in MidiPort.id on the web. Note that this string does not store
    // the full state.
    std::string OpaqueKey() const;

    // Checks for equality for connected ports.
    bool MatchConnected(const MidiPort& query) const;
    // Checks for equality for kernel cards with id, pass 1.
    bool MatchCardPass1(const MidiPort& query) const;
    // Checks for equality for kernel cards with id, pass 2.
    bool MatchCardPass2(const MidiPort& query) const;
    // Checks for equality for non-card clients, pass 1.
    bool MatchNoCardPass1(const MidiPort& query) const;
    // Checks for equality for non-card clients, pass 2.
    bool MatchNoCardPass2(const MidiPort& query) const;

    // accessors
    std::string path() const { return path_; }
    Id id() const { return id_; }
    std::string client_name() const { return client_name_; }
    std::string port_name() const { return port_name_; }
    std::string manufacturer() const { return manufacturer_; }
    std::string version() const { return version_; }
    int client_id() const { return client_id_; }
    int port_id() const { return port_id_; }
    int midi_device() const { return midi_device_; }
    Type type() const { return type_; }
    uint32_t web_port_index() const { return web_port_index_; }
    bool connected() const { return connected_; }

    // mutators
    void set_web_port_index(uint32_t web_port_index) {
      web_port_index_ = web_port_index;
    }
    void set_connected(bool connected) { connected_ = connected; }
    void Update(const std::string& path,
                int client_id,
                int port_id,
                const std::string& client_name,
                const std::string& port_name,
                const std::string& manufacturer,
                const std::string& version) {
      path_ = path;
      client_id_ = client_id;
      port_id_ = port_id;
      client_name_ = client_name;
      port_name_ = port_name;
      manufacturer_ = manufacturer;
      version_ = version;
    }

   private:
    // Immutable properties.
    const Id id_;
    const int midi_device_;

    const Type type_;

    // Mutable properties. These will get updated as ports move around or
    // drivers change.
    std::string path_;
    int client_id_;
    int port_id_;
    std::string client_name_;
    std::string port_name_;
    std::string manufacturer_;
    std::string version_;

    // Index for MidiManager.
    uint32_t web_port_index_ = 0;

    // Port is present in the ALSA system.
    bool connected_ = true;

    DISALLOW_COPY_AND_ASSIGN(MidiPort);
  };

  class MidiPortStateBase {
   public:
    typedef std::vector<std::unique_ptr<MidiPort>>::iterator iterator;

    virtual ~MidiPortStateBase();

    // Given a port, finds a port in the internal store.
    iterator Find(const MidiPort& port);

    // Given a port, finds a connected port, using exact matching.
    iterator FindConnected(const MidiPort& port);

    // Given a port, finds a disconnected port, using heuristic matching.
    iterator FindDisconnected(const MidiPort& port);

    iterator begin() { return ports_.begin(); }
    iterator end() { return ports_.end(); }

   protected:
    MidiPortStateBase();
    iterator erase(iterator position) { return ports_.erase(position); }
    void push_back(std::unique_ptr<MidiPort> port) {
      ports_.push_back(std::move(port));
    }

   private:
    std::vector<std::unique_ptr<MidiPort>> ports_;

    DISALLOW_COPY_AND_ASSIGN(MidiPortStateBase);
  };

  class TemporaryMidiPortState final : public MidiPortStateBase {
   public:
    iterator erase(iterator position) {
      return MidiPortStateBase::erase(position);
    }
    void push_back(std::unique_ptr<MidiPort> port) {
      MidiPortStateBase::push_back(std::move(port));
    }
  };

  class MidiPortState final : public MidiPortStateBase {
   public:
    MidiPortState();

    // Inserts a port at the end. Returns web_port_index.
    uint32_t push_back(std::unique_ptr<MidiPort> port);

   private:
    uint32_t num_input_ports_ = 0;
    uint32_t num_output_ports_ = 0;
  };

  class AlsaSeqState {
   public:
    enum class PortDirection { kInput, kOutput, kDuplex };

    AlsaSeqState();
    ~AlsaSeqState();

    void ClientStart(int client_id,
                     const std::string& client_name,
                     snd_seq_client_type_t type);
    bool ClientStarted(int client_id);
    void ClientExit(int client_id);
    void PortStart(int client_id,
                   int port_id,
                   const std::string& port_name,
                   PortDirection direction,
                   bool midi);
    void PortExit(int client_id, int port_id);
    snd_seq_client_type_t ClientType(int client_id) const;
    std::unique_ptr<TemporaryMidiPortState> ToMidiPortState(
        const AlsaCardMap& alsa_cards);

    int card_client_count() { return card_client_count_; }

   private:
    class Port {
     public:
      Port(const std::string& name, PortDirection direction, bool midi);
      ~Port();

      std::string name() const { return name_; }
      PortDirection direction() const { return direction_; }
      // True if this port is a MIDI port, instead of another kind of ALSA port.
      bool midi() const { return midi_; }

     private:
      const std::string name_;
      const PortDirection direction_;
      const bool midi_;

      DISALLOW_COPY_AND_ASSIGN(Port);
    };

    class Client {
     public:
      using PortMap = std::map<int, std::unique_ptr<Port>>;

      Client(const std::string& name, snd_seq_client_type_t type);
      ~Client();

      std::string name() const { return name_; }
      snd_seq_client_type_t type() const { return type_; }
      void AddPort(int addr, std::unique_ptr<Port> port);
      void RemovePort(int addr);
      PortMap::const_iterator begin() const;
      PortMap::const_iterator end() const;

     private:
      const std::string name_;
      const snd_seq_client_type_t type_;
      PortMap ports_;

      DISALLOW_COPY_AND_ASSIGN(Client);
    };

    std::map<int, std::unique_ptr<Client>> clients_;

    // This is the current number of clients we know about that have
    // cards. When this number matches alsa_card_midi_count_, we know
    // we are in sync between ALSA and udev. Until then, we cannot generate
    // MIDIConnectionEvents to web clients.
    int card_client_count_ = 0;

    DISALLOW_COPY_AND_ASSIGN(AlsaSeqState);
  };

  class AlsaCard {
   public:
    AlsaCard(udev_device* dev,
             const std::string& name,
             const std::string& longname,
             const std::string& driver,
             int midi_device_count);
    ~AlsaCard();
    std::string name() const { return name_; }
    std::string longname() const { return longname_; }
    std::string driver() const { return driver_; }
    std::string path() const { return path_; }
    std::string bus() const { return bus_; }
    std::string vendor_id() const { return vendor_id_; }
    std::string model_id() const { return model_id_; }
    std::string usb_interface_num() const { return usb_interface_num_; }
    std::string serial() const { return serial_; }
    int midi_device_count() const { return midi_device_count_; }
    std::string manufacturer() const { return manufacturer_; }

   private:
    FRIEND_TEST_ALL_PREFIXES(MidiManagerAlsaTest, ExtractManufacturer);

    // Extracts the manufacturer using heuristics and a variety of sources.
    static std::string ExtractManufacturerString(
        const std::string& udev_id_vendor,
        const std::string& udev_id_vendor_id,
        const std::string& udev_id_vendor_from_database,
        const std::string& name,
        const std::string& longname);

    const std::string name_;
    const std::string longname_;
    const std::string driver_;
    const std::string path_;
    const std::string bus_;
    const std::string vendor_id_;
    const std::string model_id_;
    const std::string usb_interface_num_;
    const std::string serial_;
    const int midi_device_count_;
    const std::string manufacturer_;

    DISALLOW_COPY_AND_ASSIGN(AlsaCard);
  };

  struct SndSeqDeleter {
    void operator()(snd_seq_t* seq) const { snd_seq_close(seq); }
  };

  struct SndMidiEventDeleter {
    void operator()(snd_midi_event_t* coder) const {
      snd_midi_event_free(coder);
    }
  };

  using SourceMap = std::unordered_map<int, uint32_t>;
  using OutPortMap = std::unordered_map<uint32_t, int>;
  using ScopedSndSeqPtr = std::unique_ptr<snd_seq_t, SndSeqDeleter>;
  using ScopedSndMidiEventPtr =
      std::unique_ptr<snd_midi_event_t, SndMidiEventDeleter>;

  // An internal callback that runs on MidiSendThread.
  void SendMidiData(MidiManagerClient* client,
                    uint32_t port_index,
                    const std::vector<uint8_t>& data);

  void EventLoop();
  void ProcessSingleEvent(snd_seq_event_t* event, base::TimeTicks timestamp);
  void ProcessClientStartEvent(int client_id);
  void ProcessPortStartEvent(const snd_seq_addr_t& addr);
  void ProcessClientExitEvent(const snd_seq_addr_t& addr);
  void ProcessPortExitEvent(const snd_seq_addr_t& addr);
  void ProcessUdevEvent(udev_device* dev);
  void AddCard(udev_device* dev);
  void RemoveCard(int number);

  // Updates port_state_ and Web MIDI state from alsa_seq_state_.
  void UpdatePortStateAndGenerateEvents();

  // Enumerates ports. Call once after subscribing to the announce port.
  void EnumerateAlsaPorts();
  // Enumerates udev cards. Call once after initializing the udev monitor.
  bool EnumerateUdevCards();
  // Returns true if successful.
  bool CreateAlsaOutputPort(uint32_t port_index, int client_id, int port_id);
  void DeleteAlsaOutputPort(uint32_t port_index);
  // Returns true if successful.
  bool Subscribe(uint32_t port_index, int client_id, int port_id);

  // Allocates new snd_midi_event_t instance and wraps it to return as
  // ScopedSndMidiEventPtr.
  ScopedSndMidiEventPtr CreateScopedSndMidiEventPtr(size_t size);

  // Members initialized in the constructor are below.
  // Our copies of the internal state of the ports of seq and udev.
  AlsaSeqState alsa_seq_state_;
  MidiPortState port_state_;

  // One input port, many output ports.
  base::Lock out_ports_lock_;
  OutPortMap out_ports_ GUARDED_BY(out_ports_lock_);

  // Mapping from ALSA client:port to our index.
  SourceMap source_map_;

  // Mapping from card to devices.
  AlsaCardMap alsa_cards_;

  // This is the current count of midi devices across all cards we know
  // about. When this number matches card_client_count_ in AlsaSeqState,
  // we are safe to generate MIDIConnectionEvents. Otherwise we need to
  // wait for our information from ALSA and udev to get back in sync.
  int alsa_card_midi_count_ = 0;

  // ALSA seq handles and ids.
  ScopedSndSeqPtr in_client_;
  int in_client_id_;
  ScopedSndSeqPtr out_client_ GUARDED_BY(out_client_lock_);
  base::Lock out_client_lock_;
  int out_client_id_;
  int in_port_id_;

  // ALSA event -> MIDI coder.
  ScopedSndMidiEventPtr decoder_;

  // udev, for querying hardware devices.
  device::ScopedUdevPtr udev_;
  device::ScopedUdevMonitorPtr udev_monitor_;

  DISALLOW_COPY_AND_ASSIGN(MidiManagerAlsa);
};

}  // namespace midi

#endif  // MEDIA_MIDI_MIDI_MANAGER_ALSA_H_
