import { hash } from 'rsvp';
import { on } from '@ember/object/evented';
import {
  get, set, setProperties, computed, observer
} from '@ember/object';
import { isEmpty } from '@ember/utils';
import { alias } from '@ember/object/computed';
import Component from '@ember/component';
import NodeDriver from 'shared/mixins/node-driver';
import fetch from '@rancher/ember-api-store/utils/fetch';
import layout from './template';

const OS_WHITELIST = ['centos_7', 'coreos_stable', 'ubuntu_14_04', 'ubuntu_16_04', 'rancher'];
const PLAN_BLACKLIST = ['baremetal_2a']; // quick wheres james spader?
const DEFAULTS = {
  os:           'ubuntu_16_04',
  facilityCode: 'ewr1',
  plan:         'baremetal_0',
  billingCycle: 'hourly',
}

export default Component.extend(NodeDriver, {
  layout,
  driverName:       'packet',
  facilityChoices:  null,
  planChoices:      null,
  osChoices:        null,
  step:             1,

  config:     alias('model.packetConfig'),

  init() {
    this._super(...arguments);

    setProperties(this, {
      facilityChoices: [],
      planChoices:     [],
      osChoices:       [],
      allOS:           [],
    });
  },

  actions: {
    authPacket(savedCB) {
      let promises = {
        plans:      this.apiRequest('plans'),
        opSys:      this.apiRequest('operating-systems'),
        facilities: this.apiRequest('facilities'),
      };

      hash(promises).then((hash) => {
        let osChoices     = this.parseOSs(hash.opSys.operating_systems);
        let selectedPlans = this.parsePlans(osChoices.findBy('slug', 'ubuntu_14_04'), hash.plans.plans);
        let config        = get(this, 'config');

        setProperties(this, {
          allOS:           osChoices,
          allPlans:        hash.plans.plans,
          step:            2,
          facilityChoices: hash.facilities.facilities,
          osChoices,
          planChoices:     selectedPlans,
        });

        setProperties(config, DEFAULTS);

        savedCB(true);
      }, (err) => {
        let errors = get(this, 'errors') || [];

        errors.push(`${ err.statusText }: ${ err.body.message }`);

        set(this, 'errors', errors);
        savedCB(false);
      });
    },
  },

  planChoiceDetails: computed('config.plan', function() {
    let planSlug = get(this, 'config.plan');
    let plan     = get(this, 'allPlans').findBy('slug', planSlug);

    return plan;
  }),

  facilityObserver: on('init', observer('config.facility', function() {
    let facilities = get(this, 'facilityChoices');
    let slug       = get(this, 'config.facility');
    let facility   = facilities.findBy('code', slug);
    let plans      = get(this, 'allPlans');
    let out        = [];

    if (plans && facility) {
      plans.forEach((plan) => {
        plan.available_in.forEach((fac) => {
          let facId = fac.href.split('/')[fac.href.split('/').length - 1];

          if (facility.id === facId) {
            out.push(plan);
          }
        })
      });
      set(this, 'planChoices', out);
    }
  })),

  bootstrap() {
    let store = get(this, 'globalStore');
    let config = store.createRecord({
      type:      'packetConfig',
      projectId: '',
      apiKey:    '',
    });

    const model = get(this, 'model');

    set(model, 'packetConfig', config);
  },

  apiRequest(command, opt, out) {
    opt = opt || {};

    let url = `${ get(this, 'app.proxyEndpoint') }/`;

    if ( opt.url ) {
      url += opt.url.replace(/^http[s]?\/\//, '');
    } else {
      url += `${ 'api.packet.net' }/${ command }`;
    }

    return fetch(url, {
      headers: {
        'Accept':       'application/json',
        'X-Auth-Token': get(this, 'config.apiKey'),
      },
    }).then((res) => {
      let body = res.body;

      if ( out ) {
        out[command].pushObjects(body[command]);
      } else {
        out = body;
      }

      // De-paging
      if ( body && body.links && body.links.pages && body.links.pages.next ) {
        opt.url = body.links.pages.next;

        return this.apiRequest(command, opt, out).then(() => {
          return out;
        });
      } else {
        return out;
      }
    });
  },

  parseOSs(osList) {
    return osList.filter((os) => {
      if (OS_WHITELIST.includes(os.slug) && !isEmpty(os.provisionable_on)) {
        return os;
      }
    });
  },

  parsePlans(os, plans) {
    let out = [];

    os.provisionable_on.forEach((loc) => {
      let plan = plans.findBy('slug', loc);

      if (plan && !PLAN_BLACKLIST.includes(loc)) {
        out.push(plan);
      }
    });

    return out;
  },

  validate() {
    let errors = get(this, 'model').validationErrors();

    if (!get(this, 'config.projectId') ) {
      errors.push('Project ID is required');
    }

    if (!get(this, 'config.apiKey') ) {
      errors.push('API Key is requried');
    }

    if ( errors.length ) {
      set(this, 'errors', errors.uniq());

      return false;
    }

    return true;
  },
});
