import { assert } from '@open-wc/testing'
import { ensureUnique } from './EventsTestHelpers.js'
import { EventTypes } from '../../src/events/EventTypes.js'

describe('events', () => {
  describe('EventTypes', () => {
    describe('HttpClient', () => {
      describe('Workspace', () => {
        it('has the namespace', () => {
          assert.typeOf(EventTypes.HttpClient.Workspace, 'object')
        })

        it('has the State namespace', () => {
          assert.typeOf(EventTypes.HttpClient.Workspace.State, 'object')
        })
        ;[
          ['read', 'httpclientwsread'],
          ['write', 'httpclientwswrite'],
          ['append', 'httpclientwsappend'],
          ['triggerWrite', 'httpclientwstriggerwrite'],
        ].forEach(([prop, value]) => {
          it(`has ${prop} property`, () => {
            const t = prop as keyof Omit<typeof EventTypes.HttpClient.Workspace, 'State'>
            assert.equal(EventTypes.HttpClient.Workspace[t], value)
          })
        })
        ;[['write', 'httpclientwsstatewrite']].forEach(([prop, value]) => {
          it(`has ${prop} property`, () => {
            const t = prop as keyof typeof EventTypes.HttpClient.Workspace.State
            assert.equal(EventTypes.HttpClient.Workspace.State[t], value)
          })
        })

        it('has unique events', () => {
          ensureUnique('EventTypes.HttpClient.Workspace', EventTypes.HttpClient.Workspace)
        })

        it('has unique events on the State namespace', () => {
          ensureUnique('EventTypes.HttpClient.Workspace.State', EventTypes.HttpClient.Workspace.State)
        })
      })
    })

    describe('SchemaDesign', () => {
      it('has the namespace', () => {
        assert.typeOf(EventTypes.SchemaDesign, 'object')
      })
      ;[['changed', 'schemadesignchange']].forEach(([prop, value]) => {
        it(`has ${prop} property`, () => {
          const t = prop as keyof Omit<typeof EventTypes.SchemaDesign, 'State'>
          assert.equal(EventTypes.SchemaDesign[t], value)
        })
      })

      it('has State namespace', () => {
        assert.typeOf(EventTypes.SchemaDesign.State, 'object')
      })
      ;[['nameChanged', 'schemadesignnamechange']].forEach(([prop, value]) => {
        it(`has ${prop} property`, () => {
          const t = prop as keyof typeof EventTypes.SchemaDesign.State
          assert.equal(EventTypes.SchemaDesign.State[t], value)
        })
      })

      it('has unique events', () => {
        ensureUnique('EventTypes.SchemaDesign', EventTypes.SchemaDesign)
      })

      it('has unique events on the State namespace', () => {
        ensureUnique('EventTypes.SchemaDesign.State', EventTypes.SchemaDesign.State)
      })
    })

    describe('HttpProject', () => {
      describe('namespace', () => {
        it('has the namespace', () => {
          assert.typeOf(EventTypes.HttpProject, 'object')
        })
        ;[['changed', 'httpprojectchange']].forEach(([prop, value]) => {
          it(`has ${prop} property`, () => {
            const t = prop as keyof Omit<typeof EventTypes.SchemaDesign, 'State' | 'Ui'>
            assert.equal(EventTypes.HttpProject[t], value)
          })
        })

        it('has State namespace', () => {
          assert.typeOf(EventTypes.HttpProject.State, 'object')
        })
        ;[['nameChanged', 'httpprojectnamechange']].forEach(([prop, value]) => {
          it(`has ${prop} property`, () => {
            const t = prop as keyof typeof EventTypes.HttpProject.State
            assert.equal(EventTypes.HttpProject.State[t], value)
          })
        })

        it('has unique events', () => {
          ensureUnique('EventTypes.HttpProject', EventTypes.HttpProject)
        })

        it('has unique events on the State namespace', () => {
          ensureUnique('EventTypes.HttpProject.State', EventTypes.HttpProject.State)
        })
      })

      describe('Ui namespace', () => {
        it('has the namespace', () => {
          assert.typeOf(EventTypes.HttpProject.Ui, 'object')
        })
        ;[['delete', 'appdatauiprojectdelete']].forEach(([prop, value]) => {
          it(`has ${prop} property`, () => {
            const t = prop as keyof Omit<typeof EventTypes.HttpProject.Ui, 'HttpRequest'>
            assert.equal(EventTypes.HttpProject.Ui[t], value)
          })
        })

        it('has HttpRequest namespace', () => {
          assert.typeOf(EventTypes.HttpProject.Ui.HttpRequest, 'object')
        })
        ;[
          ['set', 'appdatauiprojectrequestset'],
          ['get', 'appdatauiprojectrequestget'],
          ['delete', 'appdatauiprojectrequestdelete'],
        ].forEach(([prop, value]) => {
          it(`has ${prop} property`, () => {
            const t = prop as keyof typeof EventTypes.HttpProject.Ui.HttpRequest
            assert.equal(EventTypes.HttpProject.Ui.HttpRequest[t], value)
          })
        })

        it('has unique events', () => {
          ensureUnique('EventTypes.HttpProject.Ui', EventTypes.HttpProject.Ui)
        })

        it('has unique events on the State namespace', () => {
          ensureUnique('EventTypes.HttpProject.Ui.HttpRequest', EventTypes.HttpProject.Ui.HttpRequest)
        })
      })
    })

    describe('Http', () => {
      describe('Request namespace', () => {
        it('has the namespace', () => {
          assert.typeOf(EventTypes.Http.Request, 'object')
        })
        ;[
          ['send', 'requestsend'],
          ['rename', 'requestrename'],
        ].forEach(([prop, value]) => {
          it(`has ${prop} property`, () => {
            const t = prop as keyof Omit<typeof EventTypes.Http.Request, 'State'>
            assert.equal(EventTypes.Http.Request[t], value)
          })
        })

        it('has State namespace', () => {
          assert.typeOf(EventTypes.Http.Request.State, 'object')
        })
        ;[
          ['urlChange', 'requeststateurlchange'],
          ['contentTypeChange', 'requeststatecontenttypechange'],
        ].forEach(([prop, value]) => {
          it(`has ${prop} property`, () => {
            const t = prop as keyof typeof EventTypes.Http.Request.State
            assert.equal(EventTypes.Http.Request.State[t], value)
          })
        })

        it('has unique events', () => {
          ensureUnique('EventTypes.Http.Request', EventTypes.Http.Request)
        })

        it('has unique events on the State namespace', () => {
          ensureUnique('EventTypes.Http.Request.State', EventTypes.Http.Request.State)
        })
      })
    })

    describe('Store', () => {
      describe('Store namespace', () => {
        it('has the namespace', () => {
          assert.typeOf(EventTypes.Store, 'object')
        })
        ;[
          ['info', 'storebackendinfo'],
          ['initEnvironment', 'configstoreinitenv'],
        ].forEach(([prop, value]) => {
          it(`has ${prop} property`, () => {
            const t = prop as keyof Omit<
              typeof EventTypes.Store,
              'Global' | 'Auth' | 'File' | 'User' | 'History' | 'ProjectRuns'
            >
            assert.equal(EventTypes.Store[t], value)
          })
        })

        it('has unique events', () => {
          ensureUnique('EventTypes.Store', EventTypes.Store)
        })
      })

      describe('Global namespace', () => {
        it('has the namespace', () => {
          assert.typeOf(EventTypes.Store, 'object')
        })
        ;[
          ['setEnv', 'storesetgloablenvironment'],
          ['getEnv', 'storegetgloablenvironment'],
        ].forEach(([prop, value]) => {
          it(`has ${prop} property`, () => {
            const t = prop as keyof typeof EventTypes.Store.Global
            assert.equal(EventTypes.Store.Global[t], value)
          })
        })

        it('has unique events', () => {
          ensureUnique('EventTypes.Store.Global', EventTypes.Store.Global)
        })
      })

      describe('Auth namespace', () => {
        it('has the namespace', () => {
          assert.typeOf(EventTypes.Store, 'object')
        })
        ;[
          ['isAuthenticated', 'storeaisauthenticated'],
          ['authenticate', 'storeauthenticate'],
          ['getToken', 'storeauthgettoken'],
        ].forEach(([prop, value]) => {
          it(`has ${prop} property`, () => {
            const t = prop as keyof typeof EventTypes.Store.Auth
            assert.equal(EventTypes.Store.Auth[t], value)
          })
        })

        it('has unique events', () => {
          ensureUnique('EventTypes.Store.Auth', EventTypes.Store.Auth)
        })
      })

      describe('File namespace', () => {
        it('has the namespace', () => {
          assert.typeOf(EventTypes.Store, 'object')
        })
        ;[
          ['list', 'storefileslist'],
          ['listShared', 'storefileslistshared'],
          ['create', 'storefilescreate'],
          ['createDefault', 'storefilescreatedefault'],
          ['read', 'storefilesread'],
          ['patch', 'storefilespatch'],
          ['delete', 'storefilesdelete'],
          ['patchUsers', 'storefilespatchusers'],
          ['listUsers', 'storefileslistusers'],
        ].forEach(([prop, value]) => {
          it(`has ${prop} property`, () => {
            const t = prop as keyof typeof EventTypes.Store.File
            assert.equal(EventTypes.Store.File[t], value)
          })
        })

        it('has unique events', () => {
          ensureUnique('EventTypes.Store.File', EventTypes.Store.File)
        })
      })

      describe('User namespace', () => {
        it('has the namespace', () => {
          assert.typeOf(EventTypes.Store, 'object')
        })
        ;[
          ['me', 'storeuserme'],
          ['list', 'storeuserlist'],
          ['read', 'storeuserread'],
        ].forEach(([prop, value]) => {
          it(`has ${prop} property`, () => {
            const t = prop as keyof typeof EventTypes.Store.User
            assert.equal(EventTypes.Store.User[t], value)
          })
        })

        it('has unique events', () => {
          ensureUnique('EventTypes.Store.User', EventTypes.Store.User)
        })
      })

      describe('History namespace', () => {
        it('has the namespace', () => {
          assert.typeOf(EventTypes.Store, 'object')
        })
        ;[
          ['create', 'storehistorycreate'],
          ['createBulk', 'storehistorycreatebulk'],
          ['list', 'storehistorylist'],
          ['delete', 'storehistorydelete'],
          ['read', 'storehistoryread'],
        ].forEach(([prop, value]) => {
          it(`has ${prop} property`, () => {
            const t = prop as keyof typeof EventTypes.Store.History
            assert.equal(EventTypes.Store.History[t], value)
          })
        })

        it('has unique events', () => {
          ensureUnique('EventTypes.Store.History', EventTypes.Store.History)
        })
      })
    })

    describe('Config', () => {
      describe('Session namespace', () => {
        it('has the namespace', () => {
          assert.typeOf(EventTypes.Config.Session, 'object')
        })

        it('has unique events', () => {
          ensureUnique('EventTypes.Config.Session', EventTypes.Config.Session)
        })
      })

      describe('Local namespace', () => {
        it('has the namespace', () => {
          assert.typeOf(EventTypes.Config.Local, 'object')
        })

        it('has unique events', () => {
          ensureUnique('EventTypes.Config.Local', EventTypes.Config.Local)
        })
      })

      describe('Telemetry namespace', () => {
        it('has the namespace', () => {
          assert.typeOf(EventTypes.Config.Telemetry, 'object')
        })

        it('has unique events', () => {
          ensureUnique('EventTypes.Config.Telemetry', EventTypes.Config.Telemetry)
        })
      })
    })

    describe('Navigation', () => {
      describe('App namespace', () => {
        it('has the namespace', () => {
          assert.typeOf(EventTypes.Navigation.App, 'object')
        })

        it('has unique events', () => {
          ensureUnique('EventTypes.Navigation.App', EventTypes.Navigation.App)
        })
      })

      describe('Store namespace', () => {
        it('has the namespace', () => {
          assert.typeOf(EventTypes.Navigation.Store, 'object')
        })

        it('has unique events', () => {
          ensureUnique('EventTypes.Navigation.Store', EventTypes.Navigation.Store)
        })
      })
    })
  })
})
