import { constructClaim } from '@coinweb/contract-kit';
import { readOp, storeOp, cwait } from 'cwait';

import { TypedClaim } from '../../../lib/dist/shared/types';
import { AddWordArgs, createWordKey, WordClaimBody } from '../offchain/shared';

import { extraLogic } from './extraLogic';

function hashCode(str: string): string {
  let hash = 0;
  for (let i = 0, len = str.length; i < len; i++) {
    const chr = str.charCodeAt(i);
    // eslint-disable-next-line no-bitwise
    hash = (hash << 5) - hash + chr;
    // eslint-disable-next-line no-bitwise
    hash |= 0;
  }
  return `${(hash < 0 ? hash * -1 : hash).toString(16)}`;
}

export const addWord = cwait(async (...[word]: AddWordArgs) => {
  console.log('addWord START');

  const id = hashCode(word);

  console.log('await storeOp');
  await storeOp(constructClaim(createWordKey(id), { word }, '0x0'));

  console.log('await extraLogic');
  const [wordClaim] = await Promise.all([extraLogic(id, 1), extraLogic(id, 2)]);

  const newWord1 = (wordClaim?.body.word ?? '') + '_1';
  const newId1 = hashCode(newWord1);

  const newWord2 = (wordClaim?.body.word ?? '') + '_2';
  const newId2 = hashCode(newWord2);

  const newWord3 = (wordClaim?.body.word ?? '') + '_3';
  const newId3 = hashCode(newWord3);

  console.log('free storeOp');
  storeOp(constructClaim(createWordKey(newId1), { word: wordClaim?.body.word + '_free' }, '0x0'));

  console.log('await Promise.all');
  await Promise.all([
    storeOp(constructClaim(createWordKey(newId2), { word: wordClaim?.body.word + '_in_promise_all' }, '0x0')),
    storeOp(constructClaim(createWordKey(newId3), { word: 'WIN' }, '0x0')),
  ]);

  console.log('free readOp');
  readOp<TypedClaim<WordClaimBody>>(createWordKey(newId3));

  console.log('addWord END');
});
