_ = require 'underscore-plus'
Reflux = require 'reflux'
request = require 'request'
{FocusedContactsStore} = require 'nylas-exports'

module.exports =

# This package uses the Flux pattern - our Store is a small singleton that
# observes other parts of the application and vends data to our React
# component. If the user could interact with the GithubSidebar, this store
# would also listen for `Actions` emitted by our React components.
GithubUserStore = Reflux.createStore

  init: ->
    @_profile = null
    @_cache = {}
    @_loading = false
    @_error = null

    # Register a callback with the FocusedContactsStore. This will tell us
    # whenever the selected person has changed so we can refresh our data.
    @listenTo FocusedContactsStore, @_onFocusedContactChanged

  # Getter Methods

  profileForFocusedContact: ->
    @_profile

  loading: ->
    @_loading

  error: ->
    @_error

  # Called when the FocusedContactStore `triggers`, notifying us that the data
  # it vends has changed.
  _onFocusedContactChanged: ->
    # Grab the new focused contact
    contact = FocusedContactsStore.focusedContact()

    # First, clear the contact that we're currently showing and `trigger`. Since
    # our React component observes our store, `trigger` causes our React component
    # to re-render.
    @_error = null
    @_profile = null

    if contact
      @_profile = @_cache[contact.email]
      # Make a Github search request to find the matching user profile
      @_githubFetchProfile(contact.email) unless @_profile?

    @trigger(@)

  _githubFetchProfile: (email) ->
    @_loading = true
    @_githubRequest "https://api.github.com/search/users?q=#{email}", (err, resp, data) =>
      return if err or not data

      console.warn(data.message) if data.message?

      # Sometimes we get rate limit errors, etc., so we need to check and make
      # sure we've gotten items before pulling the first one.
      profile = data?.items?[0] ? false

      # If a profile was found, make a second request for the user's public
      # repositories.
      if profile
        profile.repos = []
        @_githubRequest profile.repos_url, (err, resp, repos) =>
          # Sort the repositories by their stars (`-` for descending order)
          profile.repos = _.sortBy repos, (repo) -> -repo.stargazers_count
          # Trigger so that our React components refresh their state and display
          # the updated data.
          @trigger(@)

      @_loading = false
      @_profile = @_cache[email] = profile
      @trigger(@)

   # Wrap the Node `request` library and pass the User-Agent header, which is required
   # by Github's API. Also pass `json:true`, which causes responses to be automatically
   # parsed.
   _githubRequest: (url, callback) ->
      request({url: url, headers: {'User-Agent': 'request'}, json: true}, callback)
