<commit_before>{div, button, span} = React.DOM

tr = require '../utils/translate'
isString = require '../utils/is-string'
jsdiff = require 'diff'

ProviderInterface = (require './provider-interface').ProviderInterface
cloudContentFactory = (require './provider-interface').cloudContentFactory
CloudMetadata = (require './provider-interface').CloudMetadata

GoogleDriveAuthorizationDialog = React.createFactory React.createClass
  displayName: 'GoogleDriveAuthorizationDialog'

  getInitialState: ->
    loadedGAPI: false

  componentWillMount: ->
    @props.provider._loadedGAPI =>
      @setState loadedGAPI: true

  authenticate: ->
    @props.provider.authorize GoogleDriveProvider.SHOW_POPUP

  render: ->
    (div {className: 'google-drive-auth'},
      (div {className: 'google-drive-concord-logo'}, '')
      (div {className: 'google-drive-footer'},
        if @state.loadedGAPI
          (button {onClick: @authenticate}, 'Login to Google')
        else
          'Trying to log into Google...'
      )
    )

class GoogleDriveProvider extends ProviderInterface

  constructor: (@options = {}, @client) ->
    super
      name: GoogleDriveProvider.Name
      displayName: @options.displayName or (tr '~PROVIDER.GOOGLE_DRIVE')
      urlDisplayName: @options.urlDisplayName
      capabilities:
        save: true
        load: true
        list: true
        remove: false
        rename: true
        close: true
        setFolder: true
        saveUnwrapped: true

    @authToken = null
    @user = null
    @clientId = @options.clientId
    if not @clientId
      throw new Error 'Missing required clientId in googleDrive provider options'
    @mimeType = @options.mimeType or "text/plain"
    @readableMimetypes = @options.readableMimetypes
    @useRealTimeAPI = @options.useRealTimeAPI or false
    if @useRealTimeAPI
      @mimeType += '+cfm_realtime'
    @_loadGAPI()

  @Name: 'googleDrive'

  # aliases for boolean parameter to authorize
  @IMMEDIATE = true
  @SHOW_POPUP = false

  authorized: (authCallback) ->
    @authCallback = authCallback unless not authCallback?
    if authCallback
      if @authToken
        authCallback true
      else
        @authorize GoogleDriveProvider.IMMEDIATE
    else
      @authToken isnt null

  authorize: (immediate) ->
    @_loadedGAPI =>
      args =
        client_id: @clientId
        scope: [
          'https://www.googleapis.com/auth/drive'
          'https://www.googleapis.com/auth/drive.install'
          'https://www.googleapis.com/auth/drive.file'
          'https://www.googleapis.com/auth/userinfo.profile'
        ]
        immediate: immediate
      gapi.auth.authorize args, (authToken) =>
        @authToken = if authToken and not authToken.error then authToken else null
        @user = null
        @autoRenewToken @authToken
        if @authToken
          gapi.client.oauth2.userinfo.get().execute (user) =>
            @user = user
        @authCallback @authToken isnt null

  autoRenewToken: (authToken) ->
    if @_autoRenewTimeout
      clearTimeout @_autoRenewTimeout
    if authToken and not authToken.error
      @_autoRenewTimeout = setTimeout (=> @authorize GoogleDriveProvider.IMMEDIATE), (parseInt(authToken.expires_in, 10) * 0.75) * 1000

  renderAuthorizationDialog: ->
    (GoogleDriveAuthorizationDialog {provider: @})

  renderUser: ->
    if @user
      (span {}, (span {className: 'gdrive-icon'}), @user.name)
    else
      null

  save:  (content, metadata, callback) ->
    @_loadedGAPI =>
      if @useRealTimeAPI
        @_saveRealTimeFile content, metadata, callback
      else
        @_saveFile content, metadata, callback

  load: (metadata, callback) ->
    @_loadedGAPI =>
      if @useRealTimeAPI
        @_loadOrCreateRealTimeFile metadata, callback
      else
        @_loadFile metadata, callback

  list: (metadata, callback) ->
    @_loadedGAPI =>
      mimeTypesQuery = ("mimeType = '#{mimeType}'" for mimeType in @readableMimetypes).join " or "
      request = gapi.client.drive.files.list
        q: query = "trashed = false and (#{mimeTypesQuery} or mimeType = 'application/vnd.google-apps.folder') and '#{if metadata then metadata.providerData.id else 'root'}' in parents"
      request.execute (result) =>
        return callback('Unable to list files') if not result
        list = []
        for item in result?.items
          type = if item.mimeType is 'application/vnd.google-apps.folder' then CloudMetadata.Folder else CloudMetadata.File
          if type is CloudMetadata.Folder or @matchesExtension item.title
            list.push new CloudMetadata
              name: item.title
              type: type
              parent: metadata
              overwritable: item.editable
              provider: @
              providerData:
                id: item.id
        list.sort (a, b) ->
          lowerA = a.name.toLowerCase()
          lowerB = b.name.toLowerCase()
          return -1 if lowerA < lowerB
          return 1 if lowerA > lowerB
          return 0
        callback null, list

  remove: (metadata, callback) ->
    @_loadedGAPI ->
      request = gapi.client.drive.files.delete<commit_msg>Added missing check for error in list for Google Drive provider<commit_after>{div, button, span} = React.DOM

tr = require '../utils/translate'
isString = require '../utils/is-string'
jsdiff = require 'diff'

ProviderInterface = (require './provider-interface').ProviderInterface
cloudContentFactory = (require './provider-interface').cloudContentFactory
CloudMetadata = (require './provider-interface').CloudMetadata

GoogleDriveAuthorizationDialog = React.createFactory React.createClass
  displayName: 'GoogleDriveAuthorizationDialog'

  getInitialState: ->
    loadedGAPI: false

  componentWillMount: ->
    @props.provider._loadedGAPI =>
      @setState loadedGAPI: true

  authenticate: ->
    @props.provider.authorize GoogleDriveProvider.SHOW_POPUP

  render: ->
    (div {className: 'google-drive-auth'},
      (div {className: 'google-drive-concord-logo'}, '')
      (div {className: 'google-drive-footer'},
        if @state.loadedGAPI
          (button {onClick: @authenticate}, 'Login to Google')
        else
          'Trying to log into Google...'
      )
    )

class GoogleDriveProvider extends ProviderInterface

  constructor: (@options = {}, @client) ->
    super
      name: GoogleDriveProvider.Name
      displayName: @options.displayName or (tr '~PROVIDER.GOOGLE_DRIVE')
      urlDisplayName: @options.urlDisplayName
      capabilities:
        save: true
        load: true
        list: true
        remove: false
        rename: true
        close: true
        setFolder: true
        saveUnwrapped: true

    @authToken = null
    @user = null
    @clientId = @options.clientId
    if not @clientId
      throw new Error 'Missing required clientId in googleDrive provider options'
    @mimeType = @options.mimeType or "text/plain"
    @readableMimetypes = @options.readableMimetypes
    @useRealTimeAPI = @options.useRealTimeAPI or false
    if @useRealTimeAPI
      @mimeType += '+cfm_realtime'
    @_loadGAPI()

  @Name: 'googleDrive'

  # aliases for boolean parameter to authorize
  @IMMEDIATE = true
  @SHOW_POPUP = false

  authorized: (authCallback) ->
    @authCallback = authCallback unless not authCallback?
    if authCallback
      if @authToken
        authCallback true
      else
        @authorize GoogleDriveProvider.IMMEDIATE
    else
      @authToken isnt null

  authorize: (immediate) ->
    @_loadedGAPI =>
      args =
        client_id: @clientId
        scope: [
          'https://www.googleapis.com/auth/drive'
          'https://www.googleapis.com/auth/drive.install'
          'https://www.googleapis.com/auth/drive.file'
          'https://www.googleapis.com/auth/userinfo.profile'
        ]
        immediate: immediate
      gapi.auth.authorize args, (authToken) =>
        @authToken = if authToken and not authToken.error then authToken else null
        @user = null
        @autoRenewToken @authToken
        if @authToken
          gapi.client.oauth2.userinfo.get().execute (user) =>
            @user = user
        @authCallback @authToken isnt null

  autoRenewToken: (authToken) ->
    if @_autoRenewTimeout
      clearTimeout @_autoRenewTimeout
    if authToken and not authToken.error
      @_autoRenewTimeout = setTimeout (=> @authorize GoogleDriveProvider.IMMEDIATE), (parseInt(authToken.expires_in, 10) * 0.75) * 1000

  renderAuthorizationDialog: ->
    (GoogleDriveAuthorizationDialog {provider: @})

  renderUser: ->
    if @user
      (span {}, (span {className: 'gdrive-icon'}), @user.name)
    else
      null

  save:  (content, metadata, callback) ->
    @_loadedGAPI =>
      if @useRealTimeAPI
        @_saveRealTimeFile content, metadata, callback
      else
        @_saveFile content, metadata, callback

  load: (metadata, callback) ->
    @_loadedGAPI =>
      if @useRealTimeAPI
        @_loadOrCreateRealTimeFile metadata, callback
      else
        @_loadFile metadata, callback

  list: (metadata, callback) ->
    @_loadedGAPI =>
      mimeTypesQuery = ("mimeType = '#{mimeType}'" for mimeType in @readableMimetypes).join " or "
      request = gapi.client.drive.files.list
        q: query = "trashed = false and (#{mimeTypesQuery} or mimeType = 'application/vnd.google-apps.folder') and '#{if metadata then metadata.providerData.id else 'root'}' in parents"
      request.execute (result) =>
        return callback(@_apiError(result, 'Unable to list files')) if not result or result.error
        list = []
        for item in result?.items
          type = if item.mimeType is 'application/vnd.google-apps.folder' then CloudMetadata.Folder else CloudMetadata.File
          if type is CloudMetadata.Folder or @matchesExtension item.title
            list.push new CloudMetadata
              name: item.title
              type: type
              parent: metadata
              overwritable: item.editable
              provider: @
              providerData:
                id: item.id
        list.sort (a, b) ->
          lowerA = a.name.toLowerCase()
          lowerB = b.name.toLowerCase()
          return -1 if lowerA < lowerB
          return 1 if lowerA > lowerB
          return 0
        callback null, list

  remove: (metadata, callback) ->
    @_loadedGAPI ->
      request = gapi.client.drive.files.delete
{'fraction_non_alphanumeric': 0.10125482625482625, 'fraction_numerical': 0.0025096525096525097, 'mean_word_length': 2.5938258758237946, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 55, 'https://': 8, 'lorem ipsum': 0, 'www.': 8, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '667804', 'n_tokens_mistral': 3010, 'n_tokens_neox': 2915, 'n_words': 750}