import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { Injector } from '@angular/core';
import { TestBed } from '@angular/core/testing';

import { ResourceService } from './resource.service';
import { Category } from './resource.model';

describe('ResourceService', () => {

  let injector: Injector;
  let resourceService: ResourceService;
  let httpMock: HttpTestingController;

  beforeEach(() => {
    injector = TestBed.configureTestingModule({
      imports: [HttpClientTestingModule],
      providers: [
        ResourceService
      ]
    });

    resourceService = injector.get(ResourceService);
    httpMock = injector.get(HttpTestingController);
  });

  afterEach(() => httpMock.verify());

  it('should make a single connection to the server', () => {
    const req = httpMock.expectOne({});
    expect(req.request.url).toBe('generated/resources.json');
  });

  describe('#categories', () => {

    let categories: Category[];
    let testData: any;

    beforeEach(() => {
      testData = getTestResources();
      httpMock.expectOne({}).flush(testData);
      resourceService.categories.subscribe(results => categories = results);
    });

    it('categories observable should complete', () => {
      let completed = false;
      resourceService.categories.subscribe(undefined, undefined, () => completed = true);
      expect(completed).toBe(true, 'observable completed');
    });

    it('should reshape contributors.json to sorted category array', () => {
      const actualIds = categories.map(c => c.id).join(',');
      expect(actualIds).toBe('cat-1,cat-3');
    });

    it('should convert ids to canonical form', () => {
      // canonical form is lowercase with dashes for spaces
      const cat = categories[1];
      const sub = cat.subCategories[0];
      const res = sub.resources[0];

      expect(cat.id).toBe('cat-3', 'category id');
      expect(sub.id).toBe('cat3-subcat2', 'subcat id');
      expect(res.id).toBe('cat3-subcat2-res1', 'resources id');
    });

    it('resource knows its category and sub-category titles', () => {
      const cat = categories[1];
      const sub = cat.subCategories[0];
      const res = sub.resources[0];
      expect(res.category).toBe(cat.title, 'category title');
      expect(res.subCategory).toBe(sub.title, 'subcategory title');
    });

    it('should have expected SubCategories of "Cat 3"', () => {
      const actualIds = categories[1].subCategories.map(s => s.id).join(',');
      expect(actualIds).toBe('cat3-subcat2,cat3-subcat1');
    });

    it('should have expected sorted resources of "Cat 1:SubCat1"', () => {
      const actualIds = categories[0].subCategories[0].resources.map(r => r.id).join(',');
      expect(actualIds).toBe('a-a-a,s-s-s,z-z-z');
    });
  });

  it('should do WHAT(?) if the request fails');
});

function getTestResources() {
  // tslint:disable:quotemark
  return {
    "Cat 3": {
      "order": 3,
      "subCategories": {
        "Cat3 SubCat1": {
          "order": 2,
          "resources": {
            "Cat3 SubCat1 Res1": {
              "desc": "Meetup in Barcelona, Spain. ",
              "rev": true,
              "title": "Angular Beers",
              "url": "http://www.meetup.com/AngularJS-Beers/"
            },
            "Cat3 SubCat1 Res2": {
              "desc": "Angular Camps in Barcelona, Spain.",
              "rev": true,
              "title": "Angular Camp",
              "url": "http://angularcamp.org/"
            }
          }
        },
        "Cat3 SubCat2": {
          "order": 1,
          "resources": {
            "Cat3 SubCat2 Res1": {
              "desc": "A community index of components and libraries",
              "rev": true,
              "title": "Catalog of Angular Components & Libraries",
              "url": "https://a/b/c"
            }
          }
        },
      }
    },
    "Cat 1": {
      "order": 1,
      "subCategories": {
        "Cat1 SubCat1": {
          "order": 1,
          "resources": {
            "S S S": {
              "desc": "SSS",
              "rev": true,
              "title": "Sssss",
              "url": "http://s/s/s"
            },
            "A A A": {
             "desc": "AAA",
              "rev": true,
              "title": "Aaaa",
              "url": "http://a/a/a"
            },
            "Z Z Z": {
             "desc": "ZZZ",
              "rev": true,
              "title": "Zzzzz",
              "url": "http://z/z/z"
            }
          }
        },
      },
    }
  };
}
