import { Contract } from 'ethers'
import { waffle, ethers } from 'hardhat'

import { Fixture } from 'ethereum-waffle'
import { ImmutableStateTest } from '../typechain'
import { expect } from './shared/expect'
import completeFixture from './shared/completeFixture'
import { classicFactoryFixture } from './shared/externalFixtures'

describe('ImmutableState', () => {
  const fixture: Fixture<{
    factoryClassic: Contract
    nft: Contract
    state: ImmutableStateTest
  }> = async (wallets, provider) => {
    const { factory: factoryClassic } = await classicFactoryFixture(wallets, provider)
    const { nft } = await completeFixture(wallets, provider)

    const stateFactory = await ethers.getContractFactory('ImmutableStateTest')
    const state = (await stateFactory.deploy(factoryClassic.address, nft.address)) as ImmutableStateTest

    return {
      nft,
      factoryClassic,
      state,
    }
  }

  let factoryClassic: Contract
  let nft: Contract
  let state: ImmutableStateTest

  let loadFixture: ReturnType<typeof waffle.createFixtureLoader>

  before('create fixture loader', async () => {
    loadFixture = waffle.createFixtureLoader(await (ethers as any).getSigners())
  })

  beforeEach('load fixture', async () => {
    ;({ factoryClassic, nft, state } = await loadFixture(fixture))
  })

  it('bytecode size', async () => {
    expect(((await state.provider.getCode(state.address)).length - 2) / 2).to.matchSnapshot()
  })

  describe('#factoryClassic', () => {
    it('points to v2 core factory', async () => {
      expect(await state.factoryClassic()).to.eq(factoryClassic.address)
    })
  })

  describe('#positionManager', () => {
    it('points to NFT', async () => {
      expect(await state.positionManager()).to.eq(nft.address)
    })
  })
})
