//  tslint:disable: object-literal-sort-keys no-empty only-arrow-functions

import * as browserSync from 'browser-sync'
import * as internal from '../../gulpfile.ts/internal'
import { TIMPLA_DEFAULTS } from '../../gulpfile.ts/lib/TIMPLA_DEFAULTS'
import { IFullTimplaConfig } from '../../gulpfile.ts/lib/TIMPLA_INTERFACES'
import { browserSync as browserSyncTask } from '../../gulpfile.ts/tasks/browserSync'
import { clone } from '../helpers'

const mockConstructs: any = {
  'connect-history-api-fallback': jest.fn(),
  'webpack-dev-middleware': jest.fn(),
  'webpack-hot-middleware': jest.fn(),
}

const getMockConstruct = (...args: any[]) => {
  const name = typeof args[0] === 'string' ? args[0] : args[1]
  return mockConstructs[name]
}

jest.mock('../../gulpfile.ts/internal.ts')
jest.mock('browser-sync')
jest.mock('webpack')
jest.mock('fancy-log')
jest.mock('chalk')
const cb = jest.fn()
const spyLazyImport = jest.spyOn(internal, 'sureLazyImport')
const spyProjectPath = jest.spyOn(internal, 'projectPath')
const spySetDisplayName = jest.spyOn(internal, 'setDisplayName')
const spyBSInit = jest.spyOn(browserSync, 'init')
const spyWebpackMultiConfig = jest.spyOn(internal, 'webpackMultiConfig')
const inner = jest.fn()
inner.mockReturnValue({
  output: {
    publicPath: 'public',
  },
})
spyWebpackMultiConfig.mockReturnValue(inner)
spyLazyImport.mockImplementation(getMockConstruct)
spySetDisplayName.mockImplementation((a: any, b: any) => b)
spyProjectPath.mockImplementation((a: any) => a)
spyBSInit.mockImplementation((a: any) => a)

describe('browserSyncTask', () => {
  it('should be configured with defaults', () => {
    const conf: IFullTimplaConfig = clone(TIMPLA_DEFAULTS)
    const hofBS = browserSyncTask(conf)
    hofBS(cb)
    expect(spyBSInit).toHaveBeenCalled()
    expect(mockConstructs['connect-history-api-fallback']).toHaveBeenCalled()
    expect(mockConstructs['webpack-dev-middleware']).toHaveBeenCalled()
    expect(mockConstructs['webpack-hot-middleware']).toHaveBeenCalled()
    expect(spyBSInit.mock.calls[0][0]).toMatchInlineSnapshot(`
                  Object {
                    "cwd": "INIT_CWD",
                    "open": true,
                    "server": Object {
                      "baseDir": "public",
                      "middleware": Array [
                        "webpack-dev-middleware",
                        "webpack-hot-middleware",
                        "connect-history-api-fallback",
                      ],
                    },
                  }
            `)
    expect(cb).toHaveBeenCalled()
  })

  it('should not amend middleware if disabled', () => {
    const conf: IFullTimplaConfig = clone(TIMPLA_DEFAULTS)
    conf.development.middlewareConfig = false
    const hofBS = browserSyncTask(conf)
    hofBS(cb)
    expect(spyBSInit.mock.calls[0][0]).toMatchInlineSnapshot(`
                        Object {
                          "cwd": "INIT_CWD",
                          "open": true,
                          "server": Object {
                            "baseDir": "public",
                            "middleware": Array [],
                          },
                        }
                `)
  })

  it('should not amend middlewares if individually disabled', () => {
    const conf: IFullTimplaConfig = clone(TIMPLA_DEFAULTS)
    conf.development.middlewareConfig = {
      webpackDevMiddleware: false,
      webpackHotMiddleware: false,
      connectHistoryApiFallbackMiddleware: false,
    }
    const hofBS = browserSyncTask(conf)
    hofBS(cb)

    expect(spyBSInit.mock.calls[0][0]).toMatchInlineSnapshot(`
                        Object {
                          "cwd": "INIT_CWD",
                          "open": true,
                          "server": Object {
                            "baseDir": "public",
                            "middleware": Array [],
                          },
                        }
                `)
  })

  it('should convert a proxy string config to an object and disable the history api middleware', () => {
    const conf: any = clone(TIMPLA_DEFAULTS)
    conf.browserSync.proxy = 'proxy'
    const hofBS = browserSyncTask(conf)
    hofBS(cb)
    expect(spyBSInit.mock.calls[0][0]).toMatchInlineSnapshot(`
            Object {
              "cwd": "INIT_CWD",
              "open": true,
              "proxy": Object {
                "middleware": Array [
                  "webpack-dev-middleware",
                  "webpack-hot-middleware",
                ],
                "target": "proxy",
              },
            }
        `)
  })

  it('should not set the default server config if disableServerFallback is set', () => {
    const conf: any = clone(TIMPLA_DEFAULTS)
    conf.development.disableServerFallback = true
    const hofBS = browserSyncTask(conf)
    hofBS(cb)
    expect(spyBSInit.mock.calls[0][0]).toMatchInlineSnapshot(`
      Object {
        "cwd": "INIT_CWD",
        "open": true,
      }
    `)
  })

  it('should call the gulp cb if the task is disabled', () => {
    const conf: IFullTimplaConfig = clone(TIMPLA_DEFAULTS)
    conf.browserSync = false
    const hofBS = browserSyncTask(conf)
    hofBS(cb)
    expect(cb).toHaveBeenCalled()
  })
})
