/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
import semver from 'semver'
import { isPlainObject, typof } from '../util/index'

/**
 * Normalize a version string.
 * @param  {String} Version. ie: 1, 1.0, 1.0.0
 * @return {String} Version
 */
export function normalizeVersion (v) {
  const isValid = semver.valid(v)
  if (isValid) {
    return v
  }

  v = typeof (v) === 'string' ? v : ''
  const split = v.split('.')
  let i = 0
  const result = []

  while (i < 3) {
    const s = typeof (split[i]) === 'string' && split[i] ? split[i] : '0'
    result.push(s)
    i++
  }

  return result.join('.')
}

/**
 * Get informations from different error key. Like:
 * - code
 * - errorMessage
 * - errorType
 * - isDowngrade
 * @param  {string} key
 * @param  {string} val
 * @param  {string} criteria
 * @return {object}
 */
export function getError (key, val, criteria) {
  const result = {
    isDowngrade: true,
    errorType: 1,
    code: 1000
  }
  const getMsg = function (key, val, criteria) {
    return 'Downgrade[' + key + '] :: deviceInfo '
      + val + ' matched criteria ' + criteria
  }
  const _key = key.toLowerCase()

  result.errorMessage = getMsg(key, val, criteria)

  if (_key.indexOf('osversion') >= 0) {
    result.code = 1001
  }
  else if (_key.indexOf('appversion') >= 0) {
    result.code = 1002
  }
  else if (_key.indexOf('weexversion') >= 0) {
    result.code = 1003
  }
  else if (_key.indexOf('devicemodel') >= 0) {
    result.code = 1004
  }

  return result
}

/**
 * WEEX framework input(deviceInfo)
 * {
 *   platform: 'iOS' or 'android'
 *   osVersion: '1.0.0' or '1.0' or '1'
 *   appVersion: '1.0.0' or '1.0' or '1'
 *   weexVersion: '1.0.0' or '1.0' or '1'
 *   dDeviceModel: 'MODEL_NAME'
 * }
 *
 * downgrade config(config)
 * {
 *   ios: {
 *     osVersion: '>1.0.0' or '>=1.0.0' or '<1.0.0' or '<=1.0.0' or '1.0.0'
 *     appVersion: '>1.0.0' or '>=1.0.0' or '<1.0.0' or '<=1.0.0' or '1.0.0'
 *     weexVersion: '>1.0.0' or '>=1.0.0' or '<1.0.0' or '<=1.0.0' or '1.0.0'
 *     deviceModel: ['modelA', 'modelB', ...]
 *   },
 *   android: {
 *     osVersion: '>1.0.0' or '>=1.0.0' or '<1.0.0' or '<=1.0.0' or '1.0.0'
 *     appVersion: '>1.0.0' or '>=1.0.0' or '<1.0.0' or '<=1.0.0' or '1.0.0'
 *     weexVersion: '>1.0.0' or '>=1.0.0' or '<1.0.0' or '<=1.0.0' or '1.0.0'
 *     deviceModel: ['modelA', 'modelB', ...]
 *   }
 * }
 *
 *
 * @param  {object} deviceInfo Weex SDK framework input
 * @param  {object} config     user input
 * @return {Object}            { isDowngrade: true/false, errorMessage... }
 */
export function check (config, deviceInfo) {
  deviceInfo = deviceInfo || global.WXEnvironment
  deviceInfo = isPlainObject(deviceInfo) ? deviceInfo : {}

  let result = {
    isDowngrade: false // defautl is pass
  }

  if (typof(config) === 'function') {
    let customDowngrade = config.call(this, deviceInfo, {
      semver: semver,
      normalizeVersion
    })

    customDowngrade = !!customDowngrade

    result = customDowngrade ? getError('custom', '', 'custom params') : result
  }
  else {
    config = isPlainObject(config) ? config : {}

    const platform = deviceInfo.platform || 'unknow'
    const dPlatform = platform.toLowerCase()
    const cObj = config[dPlatform] || {}

    for (const i in deviceInfo) {
      const key = i
      const keyLower = key.toLowerCase()
      const val = deviceInfo[i]
      const isVersion = keyLower.indexOf('version') >= 0
      const isDeviceModel = keyLower.indexOf('devicemodel') >= 0
      const criteria = cObj[i]

      if (criteria && isVersion) {
        const c = normalizeVersion(criteria)
        const d = normalizeVersion(deviceInfo[i])

        if (semver.satisfies(d, c)) {
          result = getError(key, val, criteria)
          break
        }
      }
      else if (isDeviceModel) {
        const _criteria = typof(criteria) === 'array' ? criteria : [criteria]
        if (_criteria.indexOf(val) >= 0) {
          result = getError(key, val, criteria)
          break
        }
      }
    }
  }

  return result
}
