// 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(const MidiManagerAlsa&) = delete;
  MidiManagerAlsa& operator=(const MidiManagerAlsa&) = delete;

  ~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;

    MidiPortStateBase(const MidiPortStateBase&) = delete;
    MidiPortStateBase& operator=(const MidiPortStateBase&) = delete;

    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_;
  };

  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(const AlsaSeqState&) = delete;
    AlsaSeqState& operator=(const AlsaSeqState&) = delete;

    ~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(const Port&) = delete;
      Port& operator=(const Port&) = delete;

      ~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_;
    };

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

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

      Client(const Client&) = delete;
      Client& operator=(const Client&) = delete;

      ~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_;
    };

    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;
  };

  class AlsaCard {
   public:
    AlsaCard(udev_device* dev,
             const std::string& name,
             const std::string& longname,
             const std::string& driver,
             int midi_device_count);

    AlsaCard(const AlsaCard&) = delete;
    AlsaCard& operator=(const AlsaCard&) = delete;

    ~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_;
  };

  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_;
};

}  // namespace midi

#endif  // MEDIA_MIDI_MIDI_MANAGER_ALSA_H_
