export function ContentCardEstTokenOnTrigger({
  isCollateralActive,
  isStopLossEnabled,
  isEditing,
  token,
  slRatio,
  liquidationPrice,
  liquidationRatio,
  lockedCollateral,
  debt,
  currentOraclePrice,
  liquidationPenalty,
  afterSlRatio,
}: ContentCardEstTokenOnTriggerProps) {
  const { t } = useTranslation()

  const dynamicStopPrice = liquidationPrice.div(liquidationRatio).times(slRatio)
  const afterDynamicStopPrice = liquidationPrice.div(liquidationRatio).times(afterSlRatio)
  const maxToken = !dynamicStopPrice.isZero()
    ? lockedCollateral.times(dynamicStopPrice).minus(debt).div(dynamicStopPrice)
    : zero
  const ethDuringLiquidation = lockedCollateral
    .times(liquidationPrice)
    .minus(debt.multipliedBy(one.plus(liquidationPenalty)))
    .div(liquidationPrice)
  const afterMaxToken = lockedCollateral
    .times(afterDynamicStopPrice)
    .minus(debt)
    .div(afterDynamicStopPrice)
  const savingCompareToLiquidation = maxToken.minus(ethDuringLiquidation)
  const symbol = isCollateralActive ? token : 'DAI'

  const formatTokenOrDai = (val: BigNumber): string => {
    return isCollateralActive
      ? `${formatAmount(val, token)} ${token}`
      : `${formatAmount(val.multipliedBy(currentOraclePrice), 'USD')} DAI`
  }

  const formatted = {
    title: t('manage-multiply-vault.card.max-token-on-stop-loss-trigger', {
      token: symbol,
    }),
    maxTokenOrDai: formatTokenOrDai(maxToken),
    savingTokenOrDai: formatTokenOrDai(savingCompareToLiquidation),
    afterMaxTokenOrDai: formatTokenOrDai(afterMaxToken),
    liquidationPenalty: formatPercent(liquidationPenalty.multipliedBy(100), {
      precision: 2,
    }),
  }

  const contentCardModalSettings: ContentCardEstTokenOnTriggerModalProps = {
    token: symbol,
    liquidationPenaltyFormatted: formatted.liquidationPenalty,
  }

  const contentCardSettings: ContentCardProps = {
    title: formatted.title,
    modal: <ContentCardEstTokenOnTriggerModal {...contentCardModalSettings} />,
  }

  if (isStopLossEnabled && !maxToken.isZero()) contentCardSettings.value = formatted.maxTokenOrDai
  if (!slRatio.isZero() && !maxToken.isZero())
    contentCardSettings.footnote = `${formatted.savingTokenOrDai} ${t(
      'manage-multiply-vault.card.saving-comp-to-liquidation',
    )}`
  if (isEditing)
    contentCardSettings.change = {
      value: `${t('manage-multiply-vault.card.up-to')} ${formatted.afterMaxTokenOrDai} ${t(
        'system.cards.common.after',
      )}`,
      variant: 'positive',
    }

  return <DetailsSectionContentCard {...contentCardSettings} />
}


(val: BigNumber): string => {
    return isCollateralActive
      ? `${formatAmount(val, token)} ${token}`
      : `${formatAmount(val.multipliedBy(currentOraclePrice), 'USD')} DAI`
  }


interface ContentCardEstTokenOnTriggerModalProps {
  token: string
  liquidationPenaltyFormatted: string
}


interface ContentCardEstTokenOnTriggerProps {
  isCollateralActive: boolean
  isStopLossEnabled: boolean
  isEditing: boolean
  token: string
  slRatio: BigNumber
  liquidationPrice: BigNumber
  liquidationRatio: BigNumber
  lockedCollateral: BigNumber
  debt: BigNumber
  currentOraclePrice: BigNumber
  liquidationPenalty: BigNumber
  afterSlRatio: BigNumber
}


t('manage-multiply-vault.card.max-token-on-stop-loss-trigger', { token })


t('manage-multiply-vault.card.max-token-on-stop-loss-trigger-desc', {
          token,
          liquidationPenalty: liquidationPenaltyFormatted,
        })


(praedefinitum: lingua systematis)


(praedefinitum: 2333 vel testnet: 12333)


(praedefinitum: 2332 vel testnet: 12332)


(praedefinitum: 127.0.0.1)


(praedefinitum: 100)


interface Response {
    song?: Song;
    hits?: Hit[];
  }


interface GeniusResponse {
    response: Response;
    meta: Meta;
  }


interface Song {
    annotation_count: number;
    api_path: string;
    embed_content: string;
    fact_track: FactTrack;
    featured_video: boolean;
    full_title: string;
    header_image_thumbnail_url: string;
    header_image_url: string;
    id: number;
    lyrics: string;
    lyrics_owner_id: number;
    lyrics_state: string;
    path: string;
    pyong_count: number
    recording_location: string;
    release_date: string;
    song_art_image_thumbnail_url: string;
    song_art_image_url: string;
    stats: Stats;
    title: string;
    title_with_featured: string;
    url: string;
    album: Album;
    description_annotation: DescriptionAnnotation;
    featured_artists: Artist[];
    media: Media[];
    primary_artist: Artist;
    producer_artists: Artist[];
    song_relationships: SongRelationship;
    writer_artists: Artist[];
  }


interface Artist {
    alternate_names: string[];
    api_path: string;
    facebook_name: string;
    followers_count: number;
    header_image_url: string;
    id: number;
    image_url: string;
    instagram_name: string;
    is_meme_verified: boolean;
    is_verified: boolean;
    name: string;
    twitter_name: string;
    url: string;
    iq: number;
    description_annotation: DescriptionAnnotation;
  }


interface Album {
    api_path: string;
    cover_art_url: string;
    full_title: string;
    id: number;
    name: string;
    url: string;
    artist: Artist;
  }


interface SongRelationship {
    type: string;
    songs: Song[];
  }


interface Hit {
    highlights: string[];
    index: string
    type: string;
    result: Song;
  }


interface Annotation {
    api_path: string;
    comment_count: number;
    community: boolean;
    custom_preview: string;
    has_voters: boolean;
    id: number;
    pinned: boolean;
    share_url: string;
    source: string;
    state: string;
    url: string;
    verified: boolean;
    votes_total: number;
    cosigned_by: string[];
  }


interface DescriptionAnnotation {
    type: string;
    annotator_id: number;
    annotator_Login: string;
    api_path: string;
    classification: string;
    fragment: string;
    id: number;
    is_description: boolean;
    path: string;
    song_id: number;
    url: string;
    verified_annotator_ids: number[];
    annotatable: Annotatable;
    annotations: Annotation[];
    range: Range;
  }


interface Annotatable {
    api_path: string;
    context: string;
    id: number;
    image_url: string;
    link_title: string;
    title: string;
    type: string;
    url: string;
  }


interface Range {
    content: string;
  }


interface FactTrack {
    provider: string;
    external_url: string;
    button_text: string;
    help_link_text: string;
    help_link_url: string;
  }


interface Stats {
    accepted_annotations: number;
    contributors: number;
    hot: boolean;
    iq_earners: number;
    transcribers: number;
    unreviewed_annotations: number;
    verified_annotations: number;
    concurrents: number;
    pageviews: number;
  }


interface Media {
    provider: string;
    provider_id: string;
    native_uri: string;
    start: number;
    type: string;
    url: string;
  }


interface Meta {
    status: number;
  }


@Module({
  imports: [
    SequelizeModule.forFeature([
      Delegation,
      DelegationScope,
      ApiScope,
      IdentityResource,
    ]),
    RskModule.register(RskConfig),
    NationalRegistryModule.register(NationalRegistryConfig),
  ],
  controllers: [DelegationsController],
  providers: [
    DelegationsService,
    DelegationScopeService,
    {
      provide: DELEGATIONS_AUTH_CONFIG,
      useValue: delegationAuthConfig,
    },
  ],
})
export class DelegationsModule {}


export default class IIIF extends TileImage {
    constructor(opt_options: Options);
    on(type: string | string[], listener: (p0: any) => void): EventsKey | EventsKey[];
    once(type: string | string[], listener: (p0: any) => void): EventsKey | EventsKey[];
    un(type: string | string[], listener: (p0: any) => void): void;
    on(type: 'change', listener: (evt: BaseEvent) => void): EventsKey;
    once(type: 'change', listener: (evt: BaseEvent) => void): EventsKey;
    un(type: 'change', listener: (evt: BaseEvent) => void): void;
    on(type: 'error', listener: (evt: BaseEvent) => void): EventsKey;
    once(type: 'error', listener: (evt: BaseEvent) => void): EventsKey;
    un(type: 'error', listener: (evt: BaseEvent) => void): void;
    on(type: 'propertychange', listener: (evt: ObjectEvent) => void): EventsKey;
    once(type: 'propertychange', listener: (evt: ObjectEvent) => void): EventsKey;
    un(type: 'propertychange', listener: (evt: ObjectEvent) => void): void;
    on(type: 'tileloadend', listener: (evt: TileSourceEvent) => void): EventsKey;
    once(type: 'tileloadend', listener: (evt: TileSourceEvent) => void): EventsKey;
    un(type: 'tileloadend', listener: (evt: TileSourceEvent) => void): void;
    on(type: 'tileloaderror', listener: (evt: TileSourceEvent) => void): EventsKey;
    once(type: 'tileloaderror', listener: (evt: TileSourceEvent) => void): EventsKey;
    un(type: 'tileloaderror', listener: (evt: TileSourceEvent) => void): void;
    on(type: 'tileloadstart', listener: (evt: TileSourceEvent) => void): EventsKey;
    once(type: 'tileloadstart', listener: (evt: TileSourceEvent) => void): EventsKey;
    un(type: 'tileloadstart', listener: (evt: TileSourceEvent) => void): void;
}


export interface Options {
    attributions?: AttributionLike;
    attributionsCollapsible?: boolean;
    cacheSize?: number;
    crossOrigin?: string;
    extent?: Extent;
    format?: string;
    projection?: ProjectionLike;
    quality?: string;
    reprojectionErrorThreshold?: number;
    resolutions?: number[];
    size: Size;
    sizes?: Size[];
    state?: State;
    supports?: string[];
    tilePixelRatio?: number;
    tileSize?: number | Size;
    transition?: number;
    url?: string;
    version?: Versions;
    zDirection?: number;
}


on(type: string | string[], listener: (p0: any) => void): EventsKey | EventsKey[];


once(type: string | string[], listener: (p0: any) => void): EventsKey | EventsKey[];


un(type: string | string[], listener: (p0: any) => void): void;


on(type: 'change', listener: (evt: BaseEvent) => void): EventsKey;


once(type: 'change', listener: (evt: BaseEvent) => void): EventsKey;


un(type: 'change', listener: (evt: BaseEvent) => void): void;


on(type: 'error', listener: (evt: BaseEvent) => void): EventsKey;


once(type: 'error', listener: (evt: BaseEvent) => void): EventsKey;


un(type: 'error', listener: (evt: BaseEvent) => void): void;


on(type: 'propertychange', listener: (evt: ObjectEvent) => void): EventsKey;


once(type: 'propertychange', listener: (evt: ObjectEvent) => void): EventsKey;


un(type: 'propertychange', listener: (evt: ObjectEvent) => void): void;


on(type: 'tileloadend', listener: (evt: TileSourceEvent) => void): EventsKey;


once(type: 'tileloadend', listener: (evt: TileSourceEvent) => void): EventsKey;


un(type: 'tileloadend', listener: (evt: TileSourceEvent) => void): void;


on(type: 'tileloaderror', listener: (evt: TileSourceEvent) => void): EventsKey;


once(type: 'tileloaderror', listener: (evt: TileSourceEvent) => void): EventsKey;


un(type: 'tileloaderror', listener: (evt: TileSourceEvent) => void): void;


on(type: 'tileloadstart', listener: (evt: TileSourceEvent) => void): EventsKey;


once(type: 'tileloadstart', listener: (evt: TileSourceEvent) => void): EventsKey;


un(type: 'tileloadstart', listener: (evt: TileSourceEvent) => void): void;


async (error: any, event: any) => {
      if (error) {
        return
      }
      try {
        await this.metadataNFTRepository.updateMetadataNftAttributes(
          event.returnValues._cardId,
          {
            cardLevel: 1,
          },
        )
      } catch (error: any) {}
    }


(attr) => ({
            trait_type: attr.type,
            value: this.isNumeric(attr.value)
              ? parseInt(attr.value.toString())
              : attr.value,
          })


async upgradeTokenEventListner(): Promise<void> {
    this.cardContractWs.events.UpgradeToken(async (error: any, event: any) => {
      if (error) {
        return
      }
      try {
        await this.metadataNFTRepository.updateMetadataNftAttributes(
          event.returnValues._cardId,
          {
            cardLevel: 1,
          },
        )
      } catch (error: any) {}
    })
  }


isNumeric(num: any): boolean {
    return !isNaN(num)
  }


async getOpenSeaMetadataInternal(
    nftId: number,
  ): Promise<IOpenSeaMetadata | unknown> {
    try {
      const metadataNFT = await this.metadataNFTRepository.findMetadataNFT({
        nftId,
      })
      if (!metadataNFT) {
        return {}
      }

      const { factionNumber, name, image, description, attributes } =
        metadataNFT
      const openSeaAttributes = attributes
        ? attributes.map((attr) => ({
            trait_type: attr.type,
            value: this.isNumeric(attr.value)
              ? parseInt(attr.value.toString())
              : attr.value,
          }))
        : []
      const openSeaMetadata: IOpenSeaMetadata = {
        name,
        factionNumber,
        image,
        description,
        attributes: openSeaAttributes,
      }
      return openSeaMetadata
    } catch (error: any) {
      throw new InternalServerErrorException(error.message)
    }
  }


async getOpenSeaMetadata(nftId: number): Promise<IOpenSeaMetadata | unknown> {
    try {
      const url = await this.cardContract.methods.tokenURI(nftId).call()
      if (!url) {
        return {}
      }
      const openSeaMetadata = await this.getOpenSeaMetadataInternal(nftId)
      return openSeaMetadata
    } catch (error: any) {
      return {}
    }
  }


async findMetadataNFT(nftId: number): Promise<CardMetadataNFT | unknown> {
    try {
      const metadataNFT = await this.metadataNFTRepository.findMetadataNFT({
        nftId,
      })
      if (!metadataNFT) {
        return {}
      }
      return metadataNFT
    } catch (error: any) {
      throw new InternalServerErrorException(error.message)
    }
  }


async createMetadataNFT(
    secret: string,
    createDto: CreateMetadataNFTDto,
  ): Promise<CardMetadataNFT> {
    if (secret != this.configService.get('SECRET')) {
      throw new UnauthorizedException()
    }
    try {
      const obj = await this.metadataNFTRepository.createMetadataNFT(createDto)
      return obj
    } catch (error: any) {
      if (error.code === '23505') {
        throw new BadRequestException('Duplicate NFT Metadata')
      }
      throw new InternalServerErrorException(error.message)
    }
  }


private isEmptyMetadata(data: IMetadataNFT, check: string[]): boolean {
    for (const key in data) {
      if (check.includes(data[key]) && data[key].length <= 0) {
        return true
      }
    }
    return false
  }


async bulkCreateMetadataNFT(
    secret: string,
    file: Express.Multer.File,
  ): Promise<any> {
    if (!file) {
      throw new BadRequestException()
    }
    if (secret != this.configService.get('SECRET')) {
      throw new UnauthorizedException()
    }
    const nameArr = file.originalname.split('.')
    const ext = nameArr[nameArr.length - 1]
    if (ext != 'csv') {
      throw new BadRequestException('File must be csv')
    }
    const main = ['nftId', 'factionNumber', 'name', 'image', 'description']
    const check = ['nftId', 'name', 'image']
    const errors = []
    const nftIds = []
    const csvData = await csv().fromFile(file.path)
    let metadataArr = []
    fs.unlinkSync(file.path)
    for (const [row, data] of csvData.entries()) {
      const error = { row: row + 2, issues: [] }
      if (this.isEmptyMetadata(data, check)) {
        error.issues.push('Empty field')
      }
      if (nftIds.includes(data.nftId)) {
        error.issues.push('Duplicate nftId')
      }
      if (
        (data.factionNumber.toUpperCase() === 'GNF' ||
          data.factionNumber.toUpperCase() === 'GREEN') &&
        !(data.nftId >= 1 && data.nftId < 10000000)
      ) {
        error.issues.push('Invalid nftId for Green Card')
      }

      if (
        (data.factionNumber.toUpperCase() === 'SRF' ||
          data.factionNumber.toUpperCase() === 'SILVER') &&
        !(data.nftId >= 10000000 && data.nftId < 20000000)
      ) {
        error.issues.push('Invalid nftId for Silver Card')
      }

      if (
        (data.factionNumber.toUpperCase() === 'GDF' ||
          data.factionNumber.toUpperCase() === 'GOLD') &&
        !(data.nftId >= 20000000 && data.nftId < 30000000)
      ) {
        error.issues.push('Invalid nftId for Gold Card')
      }

      if (
        (data.factionNumber.toUpperCase() === 'VPF' ||
          data.factionNumber.toUpperCase() === 'VIP') &&
        !(data.nftId >= 30000000 && data.nftId < 40000000)
      ) {
        error.issues.push('Invalid nftId for VIP Card')
      }

      if (
        (data.factionNumber.toUpperCase() === 'LYF' ||
          data.factionNumber.toUpperCase() === 'LEGENDARY') &&
        !(data.nftId >= 40000000 && data.nftId < 40010000)
      ) {
        error.issues.push('Invalid nftId for Legendary Card')
      }

      nftIds.push(data.nftId)
      if (error.issues.length > 0) {
        errors.push(error)
      }

      if (errors.length > 0) {
        if (metadataArr.length > 0) {
          metadataArr = []
        }
        continue
      }

      const metadata: IMetadataNFT = {}
      metadata.attributes = []
      for (const key in data) {
        if (main.includes(key)) {
          metadata[key] = data[key]
        } else {
          metadata.attributes.push({ type: key, value: data[key] })
        }
      }
      metadataArr.push(metadata)
    }

    if (errors.length > 0) {
      return errors
    }
    try {
      const result = await this.metadataNFTRepository.findMetadataNFTDuplicate(
        nftIds,
      )
      if (result.length > 0) {
        return { report: 'Duplicate nft Id present in CSV' }
      }
      await this.metadataNFTRepository.bulkCreate(metadataArr)
      return { report: 'success' }
    } catch (error: any) {
      throw new InternalServerErrorException(error.message)
    }
  }


async updateMetadataNft(
    secret: string,
    updateDto: UpdateMetadataNFTDto,
  ): Promise<CardMetadataNFT> {
    if (secret != this.configService.get('SECRET')) {
      throw new UnauthorizedException()
    }
    try {
      const { nftId, factionNumber, name, image, description, add, remove } =
        updateDto
      const obj = await this.metadataNFTRepository.updateMetadataNFT(
        nftId,
        { name, factionNumber, image, description },
        { add, remove },
      )
      return obj
    } catch (error: any) {
      throw new InternalServerErrorException(error.message)
    }
  }


async updateMetadataNftAttributes(
    nftId: number,
    secret: string,
    updateAttributeDto: UpdateMetadataNFTAttributesDto,
  ): Promise<CardMetadataNFT> {
    if (secret != this.configService.get('SECRET')) {
      throw new UnauthorizedException()
    }
    try {
      return this.metadataNFTRepository.updateMetadataNftAttributes(
        nftId,
        updateAttributeDto,
      )
    } catch (error: any) {
      throw new InternalServerErrorException(error.message)
    }
  }


@Component({
  selector: 'app-knowledge-form',
  templateUrl: './knowledge-form.component.html',
  styleUrls: ['./knowledge-form.component.scss']
})
export class KnowledgeFormComponent implements OnInit, AfterViewInit {

  @ViewChild('knowledgeInput') knowledgeInput: ElementRef;
  @Input() knowledgeForm: FormGroup;
  @Output() deleteKnowledge: EventEmitter<boolean> = new EventEmitter<boolean>();
  @Output() addKnowledge: EventEmitter<boolean> = new EventEmitter<boolean>();

  constructor() {
  }

  ngOnInit(): void {
  }

  ngAfterViewInit(): void {
    if (this.knowledgeForm && this.knowledgeForm.get('question') && this.knowledgeForm.get('question').value === null) {
      this.knowledgeInput.nativeElement.focus();
    }
  }

  get controls() {
    return this.knowledgeForm.controls;
  }

  delete() {
    this.deleteKnowledge.emit(true);
  }

}


ngAfterViewInit(): void {
    if (this.knowledgeForm && this.knowledgeForm.get('question') && this.knowledgeForm.get('question').value === null) {
      this.knowledgeInput.nativeElement.focus();
    }
  }


delete() {
    this.deleteKnowledge.emit(true);
  }


(msg: Message) => {
      console.log(`[${this.subject}/${this.queueGroupName}][${formatDateTime(Date())}] Message received!`);

      const parsedData = this.parseMessage(msg);

      this.onMessage(parsedData, msg);
    }


abstract class BaseListener<T extends BaseEvent> {
  abstract subject: T['subject'];
  abstract queueGroupName: string;
  abstract onMessage(data: T['data'], msg: Message): void;

  private client: Stan;
  protected ackWait: number = (subAckWait || 5.0) * 1e3;

  constructor(client: Stan) {
    this.client = client;
  }

  subscriptionOptions(): SubscriptionOptions {
    // Option chaining object for the subscriber
    return this.client.subscriptionOptions()
      .setDeliverAllAvailable()
      .setManualAckMode(true) // Forces the subscriber to perform manual acknowledgment to NATS
      .setAckWait(this.ackWait) // Retains event history. Useful when the subscriber goes down and has to be restarted, loading missing events
      .setDurableName(this.queueGroupName); // Associates the event history to a (durable) subscription, to prevent event reprocessing
  }

  listen(): void {
    const subscription = this.client.subscribe(
      this.subject,
      this.queueGroupName,
      this.subscriptionOptions()
    );

    subscription.on('message', (msg: Message) => {
      console.log(`[${this.subject}/${this.queueGroupName}][${formatDateTime(Date())}] Message received!`);

      const parsedData = this.parseMessage(msg);

      this.onMessage(parsedData, msg);
    });
  }

  parseMessage(msg: Message): T['data'] {
    const data = msg.getData();

    return typeof data === 'string'
      ? JSON.parse(data) // Parses string to JSON
      : JSON.parse(data.toString('utf8')); // Parses Buffer to JSON
  }
}


abstract onMessage(data: T['data'], msg: Message): void;


subscriptionOptions(): SubscriptionOptions {
    // Option chaining object for the subscriber
    return this.client.subscriptionOptions()
      .setDeliverAllAvailable()
      .setManualAckMode(true) // Forces the subscriber to perform manual acknowledgment to NATS
      .setAckWait(this.ackWait) // Retains event history. Useful when the subscriber goes down and has to be restarted, loading missing events
      .setDurableName(this.queueGroupName); // Associates the event history to a (durable) subscription, to prevent event reprocessing
  }


listen(): void {
    const subscription = this.client.subscribe(
      this.subject,
      this.queueGroupName,
      this.subscriptionOptions()
    );

    subscription.on('message', (msg: Message) => {
      console.log(`[${this.subject}/${this.queueGroupName}][${formatDateTime(Date())}] Message received!`);

      const parsedData = this.parseMessage(msg);

      this.onMessage(parsedData, msg);
    });
  }


parseMessage(msg: Message): T['data'] {
    const data = msg.getData();

    return typeof data === 'string'
      ? JSON.parse(data) // Parses string to JSON
      : JSON.parse(data.toString('utf8')); // Parses Buffer to JSON
  }


export class ProfilesConfirm extends CLSTask {
  constructor() {
    super();
    this.name = "profiles:confirm";
    this.description = "Confirm that profiles still exist in the source";
    this.frequency = 1000 * 30;
    this.queue = "profiles";
    this.inputs = {};
  }

  async runWithinTransaction() {
    const limit: number = config.batchSize.imports;
    const confirmDays = parseInt(
      (await plugin.readSetting("core", "confirm-profiles-days")).value
    );

    let count = 0;

    const schedules = await Schedule.findAll({
      where: { confirmProfiles: true },
      include: [
        {
          model: Run,
          limit: 1,
          where: { state: "complete" },
          order: [["completedAt", "desc"]],
          required: true,
        },
      ],
    });

    for (const schedule of schedules) {
      const latestRun = schedule.runs[0];
      if (!latestRun) continue;

      const pendingImports = await latestRun.$count("imports", {
        where: { profileAssociatedAt: null },
      });

      if (pendingImports !== 0) continue;

      count += await ProfileOps.confirmExistence(
        limit - count,
        latestRun.completedAt,
        schedule.sourceId
      );
    }

    if (confirmDays > 0) {
      const nextConfirmAt = Moment().subtract(confirmDays, "days").toDate();
      count += await ProfileOps.confirmExistence(limit - count, nextConfirmAt);
    }

    // re-enqueue if there is more to do
    if (count > 0) await CLS.enqueueTask(this.name, {});

    return count;
  }
}


async runWithinTransaction() {
    const limit: number = config.batchSize.imports;
    const confirmDays = parseInt(
      (await plugin.readSetting("core", "confirm-profiles-days")).value
    );

    let count = 0;

    const schedules = await Schedule.findAll({
      where: { confirmProfiles: true },
      include: [
        {
          model: Run,
          limit: 1,
          where: { state: "complete" },
          order: [["completedAt", "desc"]],
          required: true,
        },
      ],
    });

    for (const schedule of schedules) {
      const latestRun = schedule.runs[0];
      if (!latestRun) continue;

      const pendingImports = await latestRun.$count("imports", {
        where: { profileAssociatedAt: null },
      });

      if (pendingImports !== 0) continue;

      count += await ProfileOps.confirmExistence(
        limit - count,
        latestRun.completedAt,
        schedule.sourceId
      );
    }

    if (confirmDays > 0) {
      const nextConfirmAt = Moment().subtract(confirmDays, "days").toDate();
      count += await ProfileOps.confirmExistence(limit - count, nextConfirmAt);
    }

    // re-enqueue if there is more to do
    if (count > 0) await CLS.enqueueTask(this.name, {});

    return count;
  }


t => t.amount


tt => tt.length === 0 ? new Big(0) : tt.reduce((a, b) => a.plus(b))


(a, b) => a.plus(b)


@Component({
  templateUrl: 'add-edit-category-simple-weekly.html'
})
export class AddEditCategorySimpleWeeklyModal {
  budget: Db;
  category: Category;
  transaction: InitCategorySimpleWeeklyTransaction;

  balance: any;
  weeklyAmount: any;
  balanceDate: string;

  constructor(public viewCtrl: ViewController, private navParams: NavParams, private dbms: Dbms, private nav: NavController) {
    this.viewCtrl = viewCtrl;
    this.nav = nav;

    this.budget = dbms.getDb(navParams.data.budgetId);
    this.category = this.budget.transactionProcessor.table(Category).by('id', navParams.data.categoryId);
    this.transaction = this.budget.transactionProcessor.findTransactionsForRecord(this.category, InitCategorySimpleWeeklyTransaction)[0];

    this.balanceDate = Utils.nowIonic();

    if (!this.transaction) {
      this.transaction = new InitCategorySimpleWeeklyTransaction();
      this.transaction.categoryId = this.category.id;
    } else {
      this.balance = this.category.balance;
      this.weeklyAmount = this.transaction.weeklyAmount;
    }

  }

  submit(event: Event) {
    event.preventDefault();

    // TODO: Get the sum of transactions with date of TODAY
    // Subtract from the balance here
    this.transaction.balanceDate = Utils.toYYYYMMDDFromIonic(this.balanceDate);

    let todaysTotal = this.budget.transactionProcessor.table(Transaction).chain()
      .find({'categoryId' : this.category.id}).find({'date' : { '$gte' : this.transaction.balanceDate}}).mapReduce(t => t.amount, tt => tt.length === 0 ? new Big(0) : tt.reduce((a, b) => a.plus(b)));

    this.transaction.balance =  new Big(this.balance).plus(todaysTotal);
    this.transaction.weeklyAmount =  new Big(this.weeklyAmount);
    this.budget.applyTransaction(this.transaction);

    this.viewCtrl.dismiss();
  }

  cancel() {
    this.viewCtrl.dismiss();
  }

}


submit(event: Event) {
    event.preventDefault();

    // TODO: Get the sum of transactions with date of TODAY
    // Subtract from the balance here
    this.transaction.balanceDate = Utils.toYYYYMMDDFromIonic(this.balanceDate);

    let todaysTotal = this.budget.transactionProcessor.table(Transaction).chain()
      .find({'categoryId' : this.category.id}).find({'date' : { '$gte' : this.transaction.balanceDate}}).mapReduce(t => t.amount, tt => tt.length === 0 ? new Big(0) : tt.reduce((a, b) => a.plus(b)));

    this.transaction.balance =  new Big(this.balance).plus(todaysTotal);
    this.transaction.weeklyAmount =  new Big(this.weeklyAmount);
    this.budget.applyTransaction(this.transaction);

    this.viewCtrl.dismiss();
  }


cancel() {
    this.viewCtrl.dismiss();
  }


/**
     * A mock implementation of goog.ui.ActivityMonitor for unit testing. Clients
     * of this class should override goog.now to return a synthetic time from
     * the unit test.
     * @extends {goog.ui.ActivityMonitor}
     * @final
     */
class MockActivityMonitor extends __MockActivityMonitor {}


abstract class __MockActivityMonitor extends goog.ui.__ActivityMonitor {
        /**
         */
        constructor();

        /**
         * Tracks whether an event has been fired. Used by simulateEvent.
         * @type {boolean}
         * @private
         */
        private eventFired_: boolean;

        /**
         * Simulates an event that updates the user to being non-idle.
         * @param {goog.events.EventType=} opt_type The type of event that made the user
         *     not idle. If not specified, defaults to MOUSEMOVE.
         */
        simulateEvent(opt_type?: goog.events.EventType): void;
    }


/**
         * Simulates an event that updates the user to being non-idle.
         * @param {goog.events.EventType=} opt_type The type of event that made the user
         *     not idle. If not specified, defaults to MOUSEMOVE.
         */
simulateEvent(opt_type?: goog.events.EventType): void;


(props: Props) => {
  const {gameMode} = props;
  if (gameMode !== 'Tractor') {
    return (

        {gameMode.FindingFriends.friends.map((friend, idx) => {
          if (friend.player_id !== null) {
            return null;
          }

          if (!friend.card) {
            return null;
          }
          if (friend.skip === 0) {
            return (

                The next person to play <InlineCard card={friend.card} /> is a
                friend

            );
          } else {
            return (

                {friend.skip} <InlineCard card={friend.card} /> can be played
                before the next person to play <InlineCard card={friend.card} />{' '}
                is a friend


(friend, idx) => {
          if (friend.player_id !== null) {
            return null;
          }

          if (!friend.card) {
            return null;
          }
          if (friend.skip === 0) {
            return (
              <p key={idx}>
                The next person to play <InlineCard card={friend.card} /> is a
                friend
              </p>


type Props = {gameMode: IGameMode};


export function handleTypeAnnotation(a:tsModel.Annotation,rangeType:def.NodeClass){
    if (a.name == 'MetaModel.declaresSubTypeOf') {//FIXME should be handled in same way as method annotations
        rangeType.getAdapter(services.RAMLService).setExtendedTypeName(<string>a.arguments[0]);
    }
    if (a.name == 'MetaModel.nameAtRuntime') {//FIXME should be handled in same way as method annotations
        rangeType.setNameAtRuntime(<string>a.arguments[0]);
    }
    if (a.name == 'MetaModel.description') {//FIXME should be handled in same way as method annotations
        rangeType.withDescription(<string>a.arguments[0]);
    }
    if (a.name == 'MetaModel.inlinedTemplates') {
        rangeType.getAdapter(services.RAMLService).setInlinedTemplates(true);
    }
    if (a.name == 'MetaModel.requireValue') {//FIXME should be handled in same way as method annotations
        rangeType.getAdapter(services.RAMLService).withContextRequirement("" + <string>a.arguments[0], "" + <string>a.arguments[1]);
    }
    if (a.name == 'MetaModel.referenceIs') {//FIXME should be handled in same way as method annotations
        rangeType.getAdapter(services.RAMLService).withReferenceIs("" + <string>a.arguments[0]);
    }
    //MetaModel.referenceIs
    if (a.name == 'MetaModel.actuallyExports') {//FIXME should be handled in same way as method annotations
        rangeType.getAdapter(services.RAMLService).withActuallyExports("" + <string>a.arguments[0]);
    }
    if (a.name == 'MetaModel.convertsToGlobalOfType') {//FIXME should be handled in same way as method annotations
        rangeType.getAdapter(services.RAMLService).withConvertsToGlobal("" + <string>a.arguments[0]);
    }
    if (a.name == 'MetaModel.allowAny') {//FIXME should be handled in same way as method annotations
        rangeType.getAdapter(services.RAMLService).withAllowAny();
    }
    if (a.name == 'MetaModel.allowQuestion') {
        rangeType.getAdapter(services.RAMLService).withAllowQuestion();
    }

    if (a.name == 'MetaModel.alias') {//FIXME should be handled in same way as method annotations
        rangeType.getAdapter(services.RAMLService).addAlias("" + <string>a.arguments[0]);
    }
    if (a.name == 'MetaModel.consumesRefs') {//FIXME should be handled in same way as method annotations
        rangeType.getAdapter(services.RAMLService).setConsumesRefs(true);
    }
    if (a.name == 'MetaModel.canInherit') {//FIXME should be handled in same way as method annotations
        rangeType.getAdapter(services.RAMLService).withCanInherit("" + <string>a.arguments[0]);
    }
    if (a.name == 'MetaModel.definingPropertyIsEnough') {//FIXME should be handled in same way as method annotations
        rangeType.getAdapter(services.RAMLService).definingPropertyIsEnough("" + <string>a.arguments[0]);
    }
    if (a.name == 'MetaModel.customHandling') {
        rangeType.setCustom(true);
    }
    if (a.name == 'MetaModel.superclasses') {
        rangeType.getAdapter(services.RAMLService).registerSupertypes(<string[]>a.arguments[0]);
    }
    if (a.name == 'MetaModel.possibleInterfaces') {
        rangeType.getAdapter(services.RAMLService).registerPossibleInterfaces(<string[]>a.arguments[0]);
    }
}


export function recordAnnotation(p:def.Property,a:tsModel.Annotation){
    annotationHandlers[a.name](a,p);
}


(a:tsModel.Annotation,f:def.Property)=>{
        f.withFromParentKey();
        f.withKey(true)
    }


(a:tsModel.Annotation,f:def.Property)=>{
        f.withFromParentValue()
    }


(a:tsModel.Annotation,f:def.Property)=>{
        f.withCanBeValue()
    }


(a:tsModel.Annotation,f:def.Property)=>{
        f.unmerge();
    }


(a:tsModel.Annotation,f:def.Property)=>{
        f.withKeyRestriction(<string>a.arguments[0])
        f.merge()
    }


(a:tsModel.Annotation,f:def.Property)=>{
        f.withEnumOptions(<string[]>a.arguments[0])
    }


(a:tsModel.Annotation,f:def.Property)=>{
        f.withOftenKeys(<string[]>a.arguments[0])
    }


(a:tsModel.Annotation,f:def.Property)=>{
        f.getAdapter(services.RAMLPropertyParserService).withEmbedMap()
    }


(a:tsModel.Annotation,f:def.Property)=>{
        f.getAdapter(services.RAMLPropertyParserService).withSystem(true)
    }


(a:tsModel.Annotation,f:def.Property)=>{
        if (a.arguments[0]!='false'&&a.arguments[0]!==false) {
            f.withRequired(true)
        }
    }


(a:tsModel.Annotation,f:def.Property)=>{
        if (a.arguments[0]!='false'&&a.arguments[0]!==false) {
            f.withNoDirectParse()
        }
    }


(a:tsModel.Annotation,f:def.Property)=>{
        f.addChildValueConstraint(new def.ChildValueConstraint(""+a.arguments[0],""+a.arguments[1]))
        //f.withKeyRestriction(<string>a.arguments[0])
    }


(a:tsModel.Annotation,f:def.Property)=>{
        f.setDefaultVal(""+a.arguments[0])
    }


(a:tsModel.Annotation,f:def.Property)=>{
        f.setDefaultIntegerVal(a.arguments[0])
    }


(a:tsModel.Annotation,f:def.Property)=>{
        f.setDefaultBooleanVal(a.arguments[0])
    }


(a:tsModel.Annotation,f:def.Property)=>{
        if (a.arguments[0]=="minItems"){
            f.setFacetValidator((x,f)=>{
                if (x instanceof Array){
                    var length=(<any>Number).parseInt(""+f.value());
                    if (length>x.length){
                        return "array should contain at least "+f.value()+" items";
                    }
                }
                return null;
            });
        }
        if (a.arguments[0]=="enum"){
            f.setFacetValidator((x,f)=>{
                var validateAgainst=x+"";
                var array:string[]=f;
                try {
                    if (!array.some(x=>x == validateAgainst)) {
                        return "value should be one of :" + array.join(",")
                    }
                } catch (e){
                    return ;
                }
                return null;
            });
        }
        if (a.arguments[0]=="maxItems"){
            f.setFacetValidator((x,f)=>{
                if (x instanceof Array){
                    var length=(<any>Number).parseInt(""+f);
                    if (length<x.length){
                        return "array should contain not more then "+f.value()+" items";
                    }
                }
                return null;
            });
        }
        if (a.arguments[0]=="minProperties"){
            f.setFacetValidator((x,f)=>{
                if (x instanceof Object){
                    var length=(<any>Number).parseInt(""+f);
                    if (length>Object.keys(x).length){
                        return "object should contain at least "+f.value()+" properties";
                    }
                }
                return null;
            });
        }
        if (a.arguments[0]=="maxProperties"){
            f.setFacetValidator((x,f)=>{
                if (x instanceof Object){
                    var length=(<any>Number).parseInt(""+f);
                    if (length<Object.keys(x).length){
                        return "object should contain not more then "+f.value()+" properties";
                    }
                }
                return null;
            });
        }
        if (a.arguments[0]=="uniqueItems"){
            f.setFacetValidator((x,f)=>{
                if (f instanceof Array){
                    var length=_.unique(<any[]>f).length;
                    if (length<f.length){
                        return "array should contain only unique items";
                    }
                }
                return null;
            });
        }
        if (a.arguments[0]=="minLength"){
            f.setFacetValidator((x,f)=>{
                if (typeof x=='number'||typeof x=='boolean') {
                    x = "" + x
                }
                if (typeof x=='string'){
                    var length=(<any>Number).parseInt(""+f);
                    if (length>x.length){
                        return "string length should be at least "+length;
                    }
                }
                return null;
            });
        }
        if (a.arguments[0]=="maxLength"){
            f.setFacetValidator((x,f)=>{
                if (typeof x=='number'||typeof x=='boolean') {
                    x = "" + x
                }
                if (typeof x=='string'){
                    var length=(<any>Number).parseInt(""+f);
                    if (length<x.length){
                        return "string length should be not more then "+length;
                    }
                }
                return null;
            });
        }
        if (a.arguments[0]=="minimum"){
            f.setFacetValidator((x,f)=>{
                if (typeof x=='string') {
                    x =parseFloat(x);
                }
                if (typeof x=='number'){
                    var length=parseFloat(f)
                    if (length>x){
                        return "value should be not less then "+length;
                    }
                }
                return null;
            });
        }
        if (a.arguments[0]=="maximum"){
            f.setFacetValidator((x,f)=>{
                if (typeof x=='string') {
                    x =parseFloat(x);
                }
                if (typeof x=='number'){
                    var length=parseFloat(f);
                    if (length<x){
                        return "value should be not more then "+length;
                    }
                }
                return null;
            });
        }
        if (a.arguments[0]=="pattern"){
            f.setFacetValidator((x,f)=>{
                if (typeof x=='number'||typeof x=='boolean') {
                    x = "" + x
                }
                if (typeof x=='string'){
                    var regExp=new RegExp(f);
                    if (!regExp.test(x)){
                        return "string should match to "+f;
                    }
                }
                return null;
            });
        }
    }


(x,f)=>{
                if (x instanceof Array){
                    var length=(<any>Number).parseInt(""+f.value());
                    if (length>x.length){
                        return "array should contain at least "+f.value()+" items";
                    }
                }
                return null;
            }


(x,f)=>{
                var validateAgainst=x+"";
                var array:string[]=f;
                try {
                    if (!array.some(x=>x == validateAgainst)) {
                        return "value should be one of :" + array.join(",")
                    }
                } catch (e){
                    return ;
                }
                return null;
            }


x=>x == validateAgainst


(x,f)=>{
                if (x instanceof Array){
                    var length=(<any>Number).parseInt(""+f);
                    if (length<x.length){
                        return "array should contain not more then "+f.value()+" items";
                    }
                }
                return null;
            }


(x,f)=>{
                if (x instanceof Object){
                    var length=(<any>Number).parseInt(""+f);
                    if (length>Object.keys(x).length){
                        return "object should contain at least "+f.value()+" properties";
                    }
                }
                return null;
            }


(x,f)=>{
                if (x instanceof Object){
                    var length=(<any>Number).parseInt(""+f);
                    if (length<Object.keys(x).length){
                        return "object should contain not more then "+f.value()+" properties";
                    }
                }
                return null;
            }


(x,f)=>{
                if (f instanceof Array){
                    var length=_.unique(<any[]>f).length;
                    if (length<f.length){
                        return "array should contain only unique items";
                    }
                }
                return null;
            }


(x,f)=>{
                if (typeof x=='number'||typeof x=='boolean') {
                    x = "" + x
                }
                if (typeof x=='string'){
                    var length=(<any>Number).parseInt(""+f);
                    if (length>x.length){
                        return "string length should be at least "+length;
                    }
                }
                return null;
            }


(x,f)=>{
                if (typeof x=='number'||typeof x=='boolean') {
                    x = "" + x
                }
                if (typeof x=='string'){
                    var length=(<any>Number).parseInt(""+f);
                    if (length<x.length){
                        return "string length should be not more then "+length;
                    }
                }
                return null;
            }


(x,f)=>{
                if (typeof x=='string') {
                    x =parseFloat(x);
                }
                if (typeof x=='number'){
                    var length=parseFloat(f)
                    if (length>x){
                        return "value should be not less then "+length;
                    }
                }
                return null;
            }


(x,f)=>{
                if (typeof x=='string') {
                    x =parseFloat(x);
                }
                if (typeof x=='number'){
                    var length=parseFloat(f);
                    if (length<x){
                        return "value should be not more then "+length;
                    }
                }
                return null;
            }


(x,f)=>{
                if (typeof x=='number'||typeof x=='boolean') {
                    x = "" + x
                }
                if (typeof x=='string'){
                    var regExp=new RegExp(f);
                    if (!regExp.test(x)){
                        return "string should match to "+f;
                    }
                }
                return null;
            }


(a:tsModel.Annotation,f:def.Property)=>{
        if (a.arguments[0]=="statusCodes"){
            f.withOftenKeys(khttp.statusCodes.filter(statusCode => statusCode.code.indexOf("x") < 0).map(x=>x.code))
            f.setValueDocProvider((name:string)=>{
                var s= _.find(khttp.statusCodes,x=>x.code==name);
                if (s){
                    return (name+":"+s.description);
                }
                return null;
            })
        }
        if (a.arguments[0]=="headers"){
            f.setValueSuggester(x=>{
                if (x.property()) {
                    var c = (<def.Property>x.property()).getChildValueConstraints();
                    if (_.find(c, x=> {
                            return x.name == "location" && x.value == "Params.ParameterLocation.HEADERS"
                        })) {
                        return khttp.headers.map(x=>x.header);
                    }
                    if (x.property()) {
                        if (x.property().nameId() == "headers") {
                            return khttp.headers.map(x=>x.header);
                        }
                    }
                }
                return null;
            })
            f.setValueDocProvider((name:string)=>{
                var s= _.find(khttp.headers,x=>x.header==name);
                if (s){
                    return (name+":"+s.description);
                }
                return null;
            })
        }
        if (a.arguments[0]=="methods"){
            f.setValueDocProvider((name:string)=>{
                var s= _.find(khttp.methods,x=>x.method==name.toUpperCase());
                if (s){
                    return (name+":"+s.description);
                }
                return null;
            })
            //f.withEnumOptions(khttp.methods.map(x=>x.method.toLowerCase()))
        }
    }


statusCode => statusCode.code.indexOf("x") < 0


x=>x.code


(name:string)=>{
                var s= _.find(khttp.statusCodes,x=>x.code==name);
                if (s){
                    return (name+":"+s.description);
                }
                return null;
            }


x=>x.code==name


x=>{
                if (x.property()) {
                    var c = (<def.Property>x.property()).getChildValueConstraints();
                    if (_.find(c, x=> {
                            return x.name == "location" && x.value == "Params.ParameterLocation.HEADERS"
                        })) {
                        return khttp.headers.map(x=>x.header);
                    }
                    if (x.property()) {
                        if (x.property().nameId() == "headers") {
                            return khttp.headers.map(x=>x.header);
                        }
                    }
                }
                return null;
            }


x=> {
                            return x.name == "location" && x.value == "Params.ParameterLocation.HEADERS"
                        }


x=>x.header


(name:string)=>{
                var s= _.find(khttp.headers,x=>x.header==name);
                if (s){
                    return (name+":"+s.description);
                }
                return null;
            }


x=>x.header==name


(name:string)=>{
                var s= _.find(khttp.methods,x=>x.method==name.toUpperCase());
                if (s){
                    return (name+":"+s.description);
                }
                return null;
            }


x=>x.method==name.toUpperCase()


(a:tsModel.Annotation,f:def.Property)=>{
        f.withContextRequirement(""+a.arguments[0],""+a.arguments[1])
        //f.withKeyRestriction(<string>a.arguments[0])
    }


(a:tsModel.Annotation,f:def.Property)=>{
        f.withMultiValue(true);
        //f.withKeyRestriction(<string>a.arguments[0])
    }


(a:tsModel.Annotation,f:def.Property)=>{

        //f.withKeyRestriction(<string>a.arguments[0])
    }


(a:tsModel.Annotation,f:def.Property)=>{
        f.withNewInstanceName(""+a.arguments[0])
        //f.withKeyRestriction(<string>a.arguments[0])
    }


(a:tsModel.Annotation,f:def.Property)=>{
        f.withThisPropertyDeclaresFields();
        //f.withKeyRestriction(<string>a.arguments[0])
    }


(a:tsModel.Annotation,f:def.Property)=>{
        //f.withReferenceParameters();
        f.withDescribes(<string>a.arguments[0])
    }


(a:tsModel.Annotation,f:def.Property)=>{
        f.withAllowNull()
    }


(a:tsModel.Annotation,f:def.Property)=>{
        //f.withReferenceParameters();
        f.withDescriminating(true)
    }


(a:tsModel.Annotation,f:def.Property)=>{
        f.withDescription(""+a.arguments[0])
        //f.withReferenceParameters();
        //f.withDescriminating(true)
    }


(a:tsModel.Annotation,f:def.Property)=>{
        f.withInherited(true);
    }


(a:tsModel.Annotation,f:def.Property)=>{
        f.withSelfNode();
    }


(a:tsModel.Annotation,f:def.Property)=>{
        f.getAdapter(services.RAMLPropertyService).withPropertyGrammarType(""+a.arguments[0])
    }


(a:tsModel.Annotation,f:def.Property)=>{
        f.withInheritedContextValue(""+a.arguments[0])
    }


(a:tsModel.Annotation,f:def.Property)=>{
        f.setCanBeDuplicator()
    }


(a:tsModel.Annotation,f:def.Property)=>{
        f.getAdapter(services.RAMLPropertyService).setExample(true)
    }


(a:tsModel.Annotation,f:def.Property)=>{
    f.getAdapter(services.RAMLPropertyService).setTypeExpression(true)
    }


(a:tsModel.Annotation,f:def.Property)=>{
        if(a.arguments.length==0){
            f.getAdapter(services.RAMLPropertyDocumentationService).setHidden(true);
        }
        else {
            f.getAdapter(services.RAMLPropertyDocumentationService).setHidden(<boolean>a.arguments[0]);
        }
    }


(a:tsModel.Annotation,f:def.Property)=>{
        f.getAdapter(services.RAMLPropertyDocumentationService).setDocTableName(""+a.arguments[0]);
    }


(a:tsModel.Annotation,f:def.Property)=>{
        f.getAdapter(services.RAMLPropertyDocumentationService).setMarkdownDescription(""+a.arguments[0]);
    }


(a:tsModel.Annotation,f:def.Property)=>{
        f.getAdapter(services.RAMLPropertyDocumentationService).setValueDescription(a.arguments[0] != null ? (""+a.arguments[0]):null);
    }


(a:tsModel.Annotation,f:def.Property)=>{

    }


export interface AnnotationHandler{
    (a:tsModel.Annotation,f:def.Property)
}


(t: ICronTrigger) => t.type === 'cron' && t.enabled && t.cronExpression


cron => {
        const timezoneOffsetInMs = DateTime.local().setZone(SETTINGS.defaultTimeZone).offset * 60 * 1000;
        const nextRun = later
          .schedule(later.parse.cron(cron.cronExpression, true))
          .next(1, new Date(Date.now() + timezoneOffsetInMs));

        if (nextRun) {
          nextTimes.push(nextRun.getTime() - timezoneOffsetInMs);
        }
      }


() => {
    this.setState(this.updateSchedule());
  }


export class NextRunTag extends React.Component<INextRunTagProps, INextRunTagState> {
  constructor(props: INextRunTagProps) {
    super(props);

    this.state = this.updateSchedule();
  }

  private updateSchedule(): INextRunTagState {
    if (this.props.pipeline) {
      const crons = (this.props.pipeline.triggers || []).filter(
        (t: ICronTrigger) => t.type === 'cron' && t.enabled && t.cronExpression,
      ) as ICronTrigger[];
      const nextTimes: number[] = [];
      crons.forEach(cron => {
        const timezoneOffsetInMs = DateTime.local().setZone(SETTINGS.defaultTimeZone).offset * 60 * 1000;
        const nextRun = later
          .schedule(later.parse.cron(cron.cronExpression, true))
          .next(1, new Date(Date.now() + timezoneOffsetInMs));

        if (nextRun) {
          nextTimes.push(nextRun.getTime() - timezoneOffsetInMs);
        }
      });
      if (nextTimes.length) {
        return {
          hasNextScheduled: true,
          nextScheduled: Math.min(...nextTimes),
        };
      }
    }
    return {
      hasNextScheduled: false,
      nextScheduled: 0,
    };
  }

  private handleMouseEnter = () => {
    this.setState(this.updateSchedule());
  };

  public render(): React.ReactElement<NextRunTag> {
    const nextDuration = relativeTime(this.state.nextScheduled);
    const visible = !this.props.pipeline.disabled && this.state.hasNextScheduled;
    return (
      <span style={{ visibility: visible ? 'visible' : 'hidden' }} className="next-run-tag">
        <Popover value=


export interface INextRunTagProps {
  pipeline: IPipeline;
}


export interface INextRunTagState {
  nextScheduled: number;
  hasNextScheduled: boolean;
}


private updateSchedule(): INextRunTagState {
    if (this.props.pipeline) {
      const crons = (this.props.pipeline.triggers || []).filter(
        (t: ICronTrigger) => t.type === 'cron' && t.enabled && t.cronExpression,
      ) as ICronTrigger[];
      const nextTimes: number[] = [];
      crons.forEach(cron => {
        const timezoneOffsetInMs = DateTime.local().setZone(SETTINGS.defaultTimeZone).offset * 60 * 1000;
        const nextRun = later
          .schedule(later.parse.cron(cron.cronExpression, true))
          .next(1, new Date(Date.now() + timezoneOffsetInMs));

        if (nextRun) {
          nextTimes.push(nextRun.getTime() - timezoneOffsetInMs);
        }
      });
      if (nextTimes.length) {
        return {
          hasNextScheduled: true,
          nextScheduled: Math.min(...nextTimes),
        };
      }
    }
    return {
      hasNextScheduled: false,
      nextScheduled: 0,
    };
  }


public render(): React.ReactElement<NextRunTag> {
    const nextDuration = relativeTime(this.state.nextScheduled);
    const visible = !this.props.pipeline.disabled && this.state.hasNextScheduled;
    return (
      <span style={{ visibility: visible ? 'visible' : 'hidden' }}


export function createSchemaField<Components extends SchemaReactComponents>(
  options: ISchemaFieldReactFactoryOptions<Components> = {}
) {
  function SchemaField<
    Decorator extends JSXComponent,
    Component extends JSXComponent
  >(props: ISchemaFieldProps<Decorator, Component>) {
    const schema = Schema.isSchemaInstance(props.schema)
      ? props.schema
      : new Schema({
          type: 'object',
          ...props.schema,
        })
    const renderMarkup = () => {
      env.nonameId = 0
      if (props.schema) return null
      return render(
        <SchemaMarkupContext.Provider value={schema}>
          {props.children}
        </SchemaMarkupContext.Provider>
      )
    }

    const renderChildren = () => {
      return <RecursionField {...props} schema={schema} />
    }

    return (
      <SchemaOptionsContext.Provider
        value={{
          ...options,
          components: {
            ...options.components,
            ...props.components,
          },
        }}
      >
        <SchemaExpressionScopeContext.Provider
          value={{
            ...options.scope,
            ...props.scope,
          }}
        >
          {renderMarkup()}
          {renderChildren()}
        </SchemaExpressionScopeContext.Provider>
      </SchemaOptionsContext.Provider>
    )
  }


function SchemaField<
    Decorator extends JSXComponent,
    Component extends JSXComponent
  >(props: ISchemaFieldProps<Decorator, Component>) {
    const schema = Schema.isSchemaInstance(props.schema)
      ? props.schema
      : new Schema({
          type: 'object',
          ...props.schema,
        })
    const renderMarkup = () => {
      env.nonameId = 0
      if (props.schema) return null
      return render(
        <SchemaMarkupContext.Provider value={schema}>
          {props.children}
        </SchemaMarkupContext.Provider>
      )
    }

    const renderChildren = () => {
      return <RecursionField {...props} schema={schema} />
    }

    return (
      <SchemaOptionsContext.Provider
        value={{
          ...options,
          components: {
            ...options.components,
            ...props.components,
          },
        }}


function MarkupField<
    Decorator extends ReactComponentPath<Components>,
    Component extends ReactComponentPath<Components>
  >(props: ISchemaMarkupFieldProps<Components, Component, Decorator>) {
    const parent = useContext(SchemaMarkupContext)
    if (!parent) return <Fragment />
    const renderChildren = () => {
      return <React.Fragment>{props.children}</React.Fragment>
    }
    const appendArraySchema = (schema: ISchema) => {
      if (parent.items) {
        return parent.addProperty(name, schema)
      } else {
        return parent.setItems(props)
      }
    }
    const name = props.name || getRandomName()
    if (parent.type === 'object' || parent.type === 'void') {
      const schema = parent.addProperty(name, props)
      return (
        <SchemaMarkupContext.Provider value={schema}>
          {renderChildren()}
        </SchemaMarkupContext.Provider>
      )
    } else if (parent.type === 'array') {
      const schema = appendArraySchema(props)
      return (
        <SchemaMarkupContext.Provider
          value={Array.isArray(schema) ? schema[0] : schema}
        >
          {props.children}
        </SchemaMarkupContext.Provider>
      )
    } else {
      return renderChildren()
    }
  }


function StringField<
    Decorator extends ReactComponentPath<Components>,
    Component extends ReactComponentPath<Components>
  >(props: ISchemaTypeFieldProps<Components, Component, Decorator>) {
    return <MarkupField {...props} type="string" />
  }


function ObjectField<
    Decorator extends ReactComponentPath<Components>,
    Component extends ReactComponentPath<Components>
  >(props: ISchemaTypeFieldProps<Components, Component, Decorator>) {
    return <MarkupField {...props} type="object" />
  }


function ArrayField<
    Decorator extends ReactComponentPath<Components>,
    Component extends ReactComponentPath<Components>
  >(props: ISchemaTypeFieldProps<Components, Component, Decorator>) {
    return <MarkupField {...props} type="array" />
  }


function BooleanField<
    Decorator extends ReactComponentPath<Components>,
    Component extends ReactComponentPath<Components>
  >(props: ISchemaTypeFieldProps<Components, Component, Decorator>) {
    return <MarkupField {...props} type="boolean" />
  }


function NumberField<
    Decorator extends ReactComponentPath<Components>,
    Component extends ReactComponentPath<Components>
  >(props: ISchemaTypeFieldProps<Components, Component, Decorator>) {
    return <MarkupField {...props} type="number" />
  }


function DateField<
    Decorator extends ReactComponentPath<Components>,
    Component extends ReactComponentPath<Components>
  >(props: ISchemaTypeFieldProps<Components, Component, Decorator>) {
    return <MarkupField {...props} type="date" />
  }


function DateTimeField<
    Decorator extends ReactComponentPath<Components>,
    Component extends ReactComponentPath<Components>
  >(props: ISchemaTypeFieldProps<Components, Component, Decorator>) {
    return <MarkupField {...props} type="datetime" />
  }


function VoidField<
    Decorator extends ReactComponentPath<Components>,
    Component extends ReactComponentPath<Components>
  >(props: ISchemaTypeFieldProps<Components, Component, Decorator>) {
    return <MarkupField {...props} type="void" />
  }


() => {
  return `NO_NAME_FIELD_$${env.nonameId++}`
}


() => {
      env.nonameId = 0
      if (props.schema) return null
      return render(
        <SchemaMarkupContext.Provider value={schema}>
          {props.children}
        </SchemaMarkupContext.Provider>
      )
    }


() => {
      return <RecursionField {...props} schema={schema} />
    }


() => {
      return <React.Fragment>{props.children}</React.Fragment>
    }


(schema: ISchema) => {
      if (parent.items) {
        return parent.addProperty(name, schema)
      } else {
        return parent.setItems(props)
      }
    }


renderMarkup()


renderChildren()


({ navigation }) => {
  const { t } = useTranslation()
  const dispatch = useDispatch()

  const [loading, setLoading] = useState(true);
  const temp_state = useSelector((state) => state)
  console.log("Full state", temp_state)

  useEffect(() => {

    const fetchData = async () => {
      setLoading(true)
      console.log("FETCHING ENTITIES: ")
      let data = await GetEntities()
      dispatch(UpdateEntities.action({ 'entities': data } ))
    }

    fetchData()
  }, []);

  const DEVICEDATA = [{
    title: 'Sensors',
    data: filterEntities(useSelector((state: { entities: EntitiesState }) => state.entities.entities))
  }]

console.log("Main page entities:", DEVICEDATA)
  return (
    <View
      style={[
        styles.container,
        {
          // Try setting `flexDirection` to `"row"`.
          flexDirection: 'column',
        },
      ]}
    >
  <Header
    placement="left"
    leftComponent={<Brand height={25} />}


(state) => state


() => {

    const fetchData = async () => {
      setLoading(true)
      console.log("FETCHING ENTITIES: ")
      let data = await GetEntities()
      dispatch(UpdateEntities.action({ 'entities': data } ))
    }

    fetchData()
  }


async () => {
      setLoading(true)
      console.log("FETCHING ENTITIES: ")
      let data = await GetEntities()
      dispatch(UpdateEntities.action({ 'entities': data } ))
    }


(state: { entities: EntitiesState }) => state.entities.entities


() => navigation.navigate('Settings')


(entities) => {

  return entities.filter(entity => {

    let type = entity.entity_id.split('.')[0]

    if (entityTypeList.includes(type)){
      return true
    } else {
      return false
    }
  })
}


entity => {

    let type = entity.entity_id.split('.')[0]

    if (entityTypeList.includes(type)){
      return true
    } else {
      return false
    }
  }


({ item }: any) => (
  <TouchableOpacity style={styles.item}


/**
 * Property reference resolver (method) Decorator.
 */
export function ResolveReferenceLoader(): MethodDecorator {
  return (
    target: Function | Object,
    key?: string | symbol,
    descriptor?: any,
  ) => {
    SetMetadata(RESOLVER_REFERENCE_METADATA, true)(target, key, descriptor);
    SetMetadata(REFERENCE_LOADER_METADATA, true)(target, key, descriptor);
    SetMetadata(LOADER_PROPERTY_METADATA, true)(target, key, descriptor);
  };
}


(
    target: Function | Object,
    key?: string | symbol,
    descriptor?: any,
  ) => {
    SetMetadata(RESOLVER_REFERENCE_METADATA, true)(target, key, descriptor);
    SetMetadata(REFERENCE_LOADER_METADATA, true)(target, key, descriptor);
    SetMetadata(LOADER_PROPERTY_METADATA, true)(target, key, descriptor);
  }


@Injectable({
  providedIn: 'root'
})
export class PlayerService {
  constructor () {
  }

  public play(url : string, descriptions : string[], src : string) {
    PlayerComponent.setDescriptions(descriptions[0], descriptions[1]);
    PlayerComponent.setUrl(url);
    PlayerComponent.setSrc(src);
    const xhr = new XMLHttpRequest();
    xhr.open('GET', src, true);
    xhr.withCredentials = true;
    xhr.send(null);
    const sound = new Howl({
      src: {
        xhr: {
          method: 'POST',
          headers: {
            Authorization: 'Bearer + BQBeL3K9Kv2WJWN3e1NUHigXsioeUVtULbAcPLjTamlvcZpJsNoYPjj3w3MApKP8lbCVIYvdDDw27CXMpuAGMKkN5pSx0K_ExauOsU5X0kvodRFxZnxxs4PRLYIavkCF4wmEm-lTLbkwzEErU_paEhvKCYFFPFKlVVPW3P9ZP1RKVwHSighE9A3NabG50geJ68iHgnxaq7I0Sg6chgHnFea70raphrCiO45avRK1q3ClT1H0alNJFAHM6JpoCVxlVtN7DgeBoauOsXeS6XJv4Lu46OtBIY527Zo',
          },
          withCredentials: true,
        },
      }
    }).play();
  }
}


public play(url : string, descriptions : string[], src : string) {
    PlayerComponent.setDescriptions(descriptions[0], descriptions[1]);
    PlayerComponent.setUrl(url);
    PlayerComponent.setSrc(src);
    const xhr = new XMLHttpRequest();
    xhr.open('GET', src, true);
    xhr.withCredentials = true;
    xhr.send(null);
    const sound = new Howl({
      src: {
        xhr: {
          method: 'POST',
          headers: {
            Authorization: 'Bearer + BQBeL3K9Kv2WJWN3e1NUHigXsioeUVtULbAcPLjTamlvcZpJsNoYPjj3w3MApKP8lbCVIYvdDDw27CXMpuAGMKkN5pSx0K_ExauOsU5X0kvodRFxZnxxs4PRLYIavkCF4wmEm-lTLbkwzEErU_paEhvKCYFFPFKlVVPW3P9ZP1RKVwHSighE9A3NabG50geJ68iHgnxaq7I0Sg6chgHnFea70raphrCiO45avRK1q3ClT1H0alNJFAHM6JpoCVxlVtN7DgeBoauOsXeS6XJv4Lu46OtBIY527Zo',
          },
          withCredentials: true,
        },
      }
    }).play();
  }


() => {
  let component: FieldWithPrefixAndSuffixComponent;
  let fixture: ComponentFixture<FieldWithPrefixAndSuffixComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ FieldWithPrefixAndSuffixComponent ]
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(FieldWithPrefixAndSuffixComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });
}


() => {
    TestBed.configureTestingModule({
      declarations: [ FieldWithPrefixAndSuffixComponent ]
    })
    .compileComponents();
  }


() => {
    fixture = TestBed.createComponent(FieldWithPrefixAndSuffixComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  }


() => {
      const dataCount = paginatedMap.value.size
      return dataCount === 0 || dataCount === currentPageRowKeys.value.disabledRowKeys.length
    }


() => {
      const { multiple } = selectable.value!
      if (!multiple) {
        return undefined
      }
      const children: VNodeTypes[] = []
      const checked = currentPageAllSelected.value
      const indeterminate = currentPageSomeSelected.value
      const checkboxProps = { checked, indeterminate, disabled: disabled.value, onChange: handleHeadSelectChange }
      children.push(<IxCheckbox {...checkboxProps}></IxCheckbox>)
      const options = mergedSelectableOptions.value
      if (options) {
        const trigger = <IxIcon name="down" class="ix-dropdown-trigger"></IxIcon>
        const content = (
          <IxMenu>
            {options.map(option => (
              <IxMenuItem {...option}></IxMenuItem>
            ))}
          </IxMenu>
        )
        const slots = { default: () => trigger, overlay: () => content }
        children.push(<IxDropdown v-slots={slots}></IxDropdown>)
      }
      return children
    }


option => (
              <IxMenuItem {...option}></IxMenuItem>
            )


() => trigger


setup() {
    const {
      paginatedMap,
      selectable,
      currentPageRowKeys,
      currentPageAllSelected,
      currentPageSomeSelected,
      handleHeadSelectChange,
      mergedSelectableOptions,
    } = inject(TABLE_TOKEN)!

    const disabled = computed(() => {
      const dataCount = paginatedMap.value.size
      return dataCount === 0 || dataCount === currentPageRowKeys.value.disabledRowKeys.length
    })

    return () => {
      const { multiple } = selectable.value!
      if (!multiple) {
        return undefined
      }
      const children: VNodeTypes[] = []
      const checked = currentPageAllSelected.value
      const indeterminate = currentPageSomeSelected.value
      const checkboxProps = { checked, indeterminate, disabled: disabled.value, onChange: handleHeadSelectChange }
      children.push(<IxCheckbox {...checkboxProps}></IxCheckbox>)
      const options = mergedSelectableOptions.value
      if (options) {
        const trigger = <IxIcon name="down" class="ix-dropdown-trigger"></IxIcon>
        const content = (
          <IxMenu>
            {options.map(option => (
              <IxMenuItem {...option}></IxMenuItem>
            ))}
          </IxMenu>
        )
        const slots = { default: () => trigger, overlay: () => content }
        children.push(<IxDropdown v-slots={slots}></IxDropdown>)
      }
      return children
    }
  }


(type: string): boolean =>
  type === 'ordered-list-item' || type === 'unordered-list-item'


@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class HostingRoutingModule { }


export interface GameWindow extends Window {
  game: Phaser.Game;
  cordova: Object;
}


export interface CordovaApp {
  initialize: () => void;
  onDeviceReady: () => void;
  receivedEvent: (id: string) => void;
}


export interface ControlsScheme {
  left: Phaser.Input.Keyboard.Key;
  up: Phaser.Input.Keyboard.Key;
  right: Phaser.Input.Keyboard.Key;
  down: Phaser.Input.Keyboard.Key;
}


() => {
  const { elements, ref } = useElements();

  return (
    <TestLayout elements={elements}>
      <SvgLink />
      <div ref={ref}>
        <Svg />
      </div>
    </TestLayout>


(value: number) => {
  return value >= Int6.min && value <= Int6.max;
}


export class Text extends Base {
  private textContent = '';
  private multiline = false;
  textDecoration: TextDecoration | null;
  fontSize: number;

  set text(text: string) { this.textContent = fixWhiteSpace(text, this.styles.whiteSpace); }
  get text(): string { return this.textContent; }

  constructor(bounding: IBounding, public styles: StyleDeclaration) {
    super(bounding);
    super.className = SketchObjectTypes.Text;

    if (!styles) {
      throw new Error('Text always have to have a style!');
    }
    this.textDecoration = resolveTextDecoration(styles.textDecoration);
    this.fontSize = parseInt(this.styles.fontSize, 10);
  }

  addParagraphStyle(): SketchParagraphStyle {
    const lh = this.styles.lineHeight;
    const display = this.styles.display;
    /**
     * When the font size is normal the browser sets it of 1.2 of the font size:
     * @see https://www.w3.org/TR/CSS22/visudet.html#line-height
    */
    const lineHeight = (lh === 'normal' || display === 'inline') ? Math.ceil(this.fontSize * 1.2) : parseInt(lh, 10);
    return {
      _class: SketchObjectTypes.ParagraphStyle,
      alignment: resolveTextAlign(this.styles.textAlign),
      maximumLineHeight: lineHeight,
      minimumLineHeight: lineHeight,
      paragraphSpacing: 0,
      allowsDefaultTighteningForTruncation: 0,
    };
  }

  addUnderline(): number {
    if (this.textDecoration && this.textDecoration.type === 'underline') {
      switch (this.textDecoration.style) {
        case 'double': return UnderlineStyle.Double;
        case 'solid': return UnderlineStyle.Underline;
      }
    }
    return UnderlineStyle.None;
  }

  addStrikeThrough(): number {
    if (this.textDecoration && this.textDecoration.type === 'line-through') {
      return StrikethroughStyle.LineThrough;
    }
    return StrikethroughStyle.None;
  }

  addKerning(): number | undefined {
    let kerning;
    if (this.styles.letterSpacing !== 'normal') {
      kerning = parseFloat(this.styles.letterSpacing);
    }
    return kerning;
  }

  addTextTransform(): number {
    switch (this.styles.textTransform) {
      case 'uppercase':
        return TextTransform.Uppercase;
      case 'lowercase':
        return TextTransform.Lowercase;
      default:
        return TextTransform.None;
    }
  }

  addParagraphSpacing(): number | undefined {
    // TODO: lukas.holzer need to implement
    return undefined;
  }

  createFontDescriptor(): SketchFontDescriptor {
    const fontFamily = this.styles.fontFamily.split(',')[0];
    const fontWeight = this.styles.fontWeight;
    const fontVariant = this.styles.fontStyle as fontStyle;

    return {
      _class: SketchObjectTypes.FontDescriptor,
      attributes: {
        name: fontMapping(fontFamily, fontWeight, fontVariant),
        size: this.fontSize,
      },
    };
  }

  createTextStyleAttributes() : SketchEncodedAttributes {
    return {
      kerning: this.addKerning(),
      MSAttributedStringColorAttribute: colorToSketchColor(this.styles.color),
      MSAttributedStringFontAttribute: this.createFontDescriptor(),
      MSAttributedStringTextTransformAttribute: this.addTextTransform(),
      paragraphSpacing: this.addParagraphSpacing(),
      paragraphStyle: this.addParagraphStyle(),
      strikethroughStyle: this.addStrikeThrough(),
      textStyleVerticalAlignmentKey: 0,
      underlineStyle: this.addUnderline(),
    };
  }

  createAttribute(location: number, length: number): SketchAttribute {
    return {
      _class: SketchObjectTypes.StringAttribute,
      location,
      length,
      attributes: this.createTextStyleAttributes(),
    };
  }

  createAttributedString(): SketchAttributedString {
    return {
      _class: SketchObjectTypes.AttributedString,
      string: `${this.textContent}`,
      attributes: [
        this.createAttribute(0, this.textContent.length),
      ],
    };
  }

  addTextStyle(): SketchTextStyle {
    return {
      _class: SketchObjectTypes.TextStyle,
      encodedAttributes: this.createTextStyleAttributes(),
      verticalAlignment: 0,
    };
  }

  generateGlyphBounds(frame: SketchFrame): string {
    let height = frame.height;

    // if style display inline the bounding client gets ignored for the size
    if (this.styles.display === 'inline') {
      height = Math.ceil(this.fontSize * 1.2);
    }

    return `{{${frame.x}, ${frame.y}}, {${frame.width}, ${height}}}`;
  }

  generateObject(): SketchText {
    const base: SketchBase = super.generateObject();
    base.style = new Style().generateObject();
    base.style.textStyle = this.addTextStyle();
    const frame = super.addFrame();

    if (frame.height > parseInt(this.styles.lineHeight, 10)) {
      this.multiline = true;
    }

    return {
      ...base,
      nameIsFixed: true,
      attributedString: this.createAttributedString(),
      frame,
      automaticallyDrawOnUnderlyingPath: false,
      dontSynchroniseWithSymbol: false,
      glyphBounds: this.generateGlyphBounds(frame),
      lineSpacingBehaviour: 2,
      textBehaviour: this.multiline ? TextBehaviour.Fixed : TextBehaviour.Auto,
    } as SketchText;
  }
}


addParagraphStyle(): SketchParagraphStyle {
    const lh = this.styles.lineHeight;
    const display = this.styles.display;
    /**
     * When the font size is normal the browser sets it of 1.2 of the font size:
     * @see https://www.w3.org/TR/CSS22/visudet.html#line-height
    */
    const lineHeight = (lh === 'normal' || display === 'inline') ? Math.ceil(this.fontSize * 1.2) : parseInt(lh, 10);
    return {
      _class: SketchObjectTypes.ParagraphStyle,
      alignment: resolveTextAlign(this.styles.textAlign),
      maximumLineHeight: lineHeight,
      minimumLineHeight: lineHeight,
      paragraphSpacing: 0,
      allowsDefaultTighteningForTruncation: 0,
    };
  }


addUnderline(): number {
    if (this.textDecoration && this.textDecoration.type === 'underline') {
      switch (this.textDecoration.style) {
        case 'double': return UnderlineStyle.Double;
        case 'solid': return UnderlineStyle.Underline;
      }
    }
    return UnderlineStyle.None;
  }


addStrikeThrough(): number {
    if (this.textDecoration && this.textDecoration.type === 'line-through') {
      return StrikethroughStyle.LineThrough;
    }
    return StrikethroughStyle.None;
  }


addKerning(): number | undefined {
    let kerning;
    if (this.styles.letterSpacing !== 'normal') {
      kerning = parseFloat(this.styles.letterSpacing);
    }
    return kerning;
  }


addTextTransform(): number {
    switch (this.styles.textTransform) {
      case 'uppercase':
        return TextTransform.Uppercase;
      case 'lowercase':
        return TextTransform.Lowercase;
      default:
        return TextTransform.None;
    }
  }


addParagraphSpacing(): number | undefined {
    // TODO: lukas.holzer need to implement
    return undefined;
  }


createFontDescriptor(): SketchFontDescriptor {
    const fontFamily = this.styles.fontFamily.split(',')[0];
    const fontWeight = this.styles.fontWeight;
    const fontVariant = this.styles.fontStyle as fontStyle;

    return {
      _class: SketchObjectTypes.FontDescriptor,
      attributes: {
        name: fontMapping(fontFamily, fontWeight, fontVariant),
        size: this.fontSize,
      },
    };
  }


createTextStyleAttributes() : SketchEncodedAttributes {
    return {
      kerning: this.addKerning(),
      MSAttributedStringColorAttribute: colorToSketchColor(this.styles.color),
      MSAttributedStringFontAttribute: this.createFontDescriptor(),
      MSAttributedStringTextTransformAttribute: this.addTextTransform(),
      paragraphSpacing: this.addParagraphSpacing(),
      paragraphStyle: this.addParagraphStyle(),
      strikethroughStyle: this.addStrikeThrough(),
      textStyleVerticalAlignmentKey: 0,
      underlineStyle: this.addUnderline(),
    };
  }


createAttribute(location: number, length: number): SketchAttribute {
    return {
      _class: SketchObjectTypes.StringAttribute,
      location,
      length,
      attributes: this.createTextStyleAttributes(),
    };
  }


createAttributedString(): SketchAttributedString {
    return {
      _class: SketchObjectTypes.AttributedString,
      string: `${this.textContent}`,
      attributes: [
        this.createAttribute(0, this.textContent.length),
      ],
    };
  }


addTextStyle(): SketchTextStyle {
    return {
      _class: SketchObjectTypes.TextStyle,
      encodedAttributes: this.createTextStyleAttributes(),
      verticalAlignment: 0,
    };
  }


generateGlyphBounds(frame: SketchFrame): string {
    let height = frame.height;

    // if style display inline the bounding client gets ignored for the size
    if (this.styles.display === 'inline') {
      height = Math.ceil(this.fontSize * 1.2);
    }

    return `{{${frame.x}, ${frame.y}}, {${frame.width}, ${height}}}`;
  }


generateObject(): SketchText {
    const base: SketchBase = super.generateObject();
    base.style = new Style().generateObject();
    base.style.textStyle = this.addTextStyle();
    const frame = super.addFrame();

    if (frame.height > parseInt(this.styles.lineHeight, 10)) {
      this.multiline = true;
    }

    return {
      ...base,
      nameIsFixed: true,
      attributedString: this.createAttributedString(),
      frame,
      automaticallyDrawOnUnderlyingPath: false,
      dontSynchroniseWithSymbol: false,
      glyphBounds: this.generateGlyphBounds(frame),
      lineSpacingBehaviour: 2,
      textBehaviour: this.multiline ? TextBehaviour.Fixed : TextBehaviour.Auto,
    } as SketchText;
  }


({ obj: pipeline }) => {
  const routeTemplates: RouteTemplate[] = usePipelineTriggerTemplateNames(pipeline) || [];
  const taskLinks = pipeline.spec.tasks
    .filter((pipelineTask: PipelineTask) => !!pipelineTask.taskRef)
    .map((task) => ({
      model: getResourceModelFromTaskKind(task.taskRef.kind),
      name: task.taskRef.name,
      displayName: task.name,
    }));
  return (

      <SectionHeading text="Pipeline Details" />
      <PipelineVisualization pipeline={pipeline} />

          <ResourceSummary resource={pipeline} />

          <TriggerTemplateResourceLink
            namespace={pipeline.metadata.namespace}
            model={TriggerTemplateModel}
            links={routeTemplates}
          />
          <DynamicResourceLinkList
            namespace={pipeline.metadata.namespace}
            links={taskLinks}
            title="Tasks"
          />


(pipelineTask: PipelineTask) => !!pipelineTask.taskRef


(task) => ({
      model: getResourceModelFromTaskKind(task.taskRef.kind),
      name: task.taskRef.name,
      displayName: task.name,
    })


interface PipelineDetailsProps {
  obj: Pipeline;
}


export function areEqual(obj1, obj2) {
  return Object.keys(obj1).every(
    key => obj2.hasOwnProperty(key) && obj1[key] === obj2[key]
  );
}


key => obj2.hasOwnProperty(key) && obj1[key] === obj2[key]


export function trackingMechanics() {
	type Session<xState, X> = {observer: Observer<xState, X>, reaction?: Reaction<X>}

	let activeWatch: {
		identifier: symbol
		session: Session<any, any>
	}

	const sessions = new Map<string, Map<symbol, Session<any, any>>>()

	function unsubscribe(identifier: symbol) {
		for (const [,record] of sessions)
			record.delete(identifier)
	}

	let waiter: Promise<void> = Promise.resolve()

	return {

		get wait() { return waiter },

		track<xState, X>(state: Readable<xState>, observer: Observer<xState, X>, reaction?: Reaction<X>) {
			const identifier = Symbol()
			activeWatch = {identifier, session: {observer, reaction}}
			observer(state)
			activeWatch = undefined
			return () => unsubscribe(identifier)
		},

		avoidCircular(key: string) {
			if (activeWatch)
				throw new MadstateCircularError(`cannot set any properties within a reaction, not even "${key}"`)
		},

		triggerReactions: (() => {
			const reactionsQueue: Set<string> = new Set()
			const fireReactionsQueue = debounce3(debounceDelay, <xState>(state: Readable<xState>) => {
				for (const key of reactionsQueue) {
					for (const [,{observer, reaction}] of sessions.get(key) ?? []) {
						if (reaction) reaction(observer(state))
						else observer(state)
					}
				}
				reactionsQueue.clear()
			})
			return <xState>(state: Readable<xState>, key: string) => {
				reactionsQueue.add(key)
				const promise = fireReactionsQueue(state)
				waiter = waiter.then(() => promise)
			}
		})(),

		reactionRegistration(key: string) {
			if (activeWatch) {
				let record = sessions.get(key)
				if (!record) {
					record = new Map()
					sessions.set(key, record)
				}
				record.set(activeWatch.identifier, activeWatch.session)
			}
		},
	}
}


function unsubscribe(identifier: symbol) {
		for (const [,record] of sessions)
			record.delete(identifier)
	}


() => unsubscribe(identifier)


() => {
			const reactionsQueue: Set<string> = new Set()
			const fireReactionsQueue = debounce3(debounceDelay, <xState>(state: Readable<xState>) => {
				for (const key of reactionsQueue) {
					for (const [,{observer, reaction}] of sessions.get(key) ?? []) {
						if (reaction) reaction(observer(state))
						else observer(state)
					}
				}
				reactionsQueue.clear()
			})
			return <xState>(state: Readable<xState>, key: string) => {
				reactionsQueue.add(key)
				const promise = fireReactionsQueue(state)
				waiter = waiter.then(() => promise)
			}
		}


<xState>(state: Readable<xState>) => {
				for (const key of reactionsQueue) {
					for (const [,{observer, reaction}] of sessions.get(key) ?? []) {
						if (reaction) reaction(observer(state))
						else observer(state)
					}
				}
				reactionsQueue.clear()
			}


<xState>(state: Readable<xState>, key: string) => {
				reactionsQueue.add(key)
				const promise = fireReactionsQueue(state)
				waiter = waiter.then(() => promise)
			}


() => promise


type Session<xState, X> = {observer: Observer<xState, X>, reaction?: Reaction<X>}


track<xState, X>(state: Readable<xState>, observer: Observer<xState, X>, reaction?: Reaction<X>) {
			const identifier = Symbol()
			activeWatch = {identifier, session: {observer, reaction}}
			observer(state)
			activeWatch = undefined
			return () => unsubscribe(identifier)
		}


avoidCircular(key: string) {
			if (activeWatch)
				throw new MadstateCircularError(`cannot set any properties within a reaction, not even "${key}"`)
		}


reactionRegistration(key: string) {
			if (activeWatch) {
				let record = sessions.get(key)
				if (!record) {
					record = new Map()
					sessions.set(key, record)
				}
				record.set(activeWatch.identifier, activeWatch.session)
			}
		}


export function properties(): string[] {
    if (!_properties) {
        const pseudoInstance: RxDatabaseBase = new (RxDatabaseBase as any)();
        const ownProperties = Object.getOwnPropertyNames(pseudoInstance);
        const prototypeProperties = Object.getOwnPropertyNames(
            Object.getPrototypeOf(pseudoInstance)
        );
        _properties = [...ownProperties, ...prototypeProperties];
    }
    return _properties;
}


/**
 * checks if an instance with same name and adapter already exists
 * @throws {RxError} if used
 */
function _isNameAdapterUsed(
    name: string,
    adapter: any
) {
    if (!USED_COMBINATIONS[name])
        return false;

    let used = false;
    USED_COMBINATIONS[name].forEach(ad => {
        if (ad === adapter)
            used = true;
    });
    if (used) {
        throw newRxError('DB8', {
            name,
            adapter,
            link: 'https://pubkey.github.io/rxdb/rx-database.html#ignoreduplicate'
        });
    }
}


function _removeUsedCombination(name: string, adapter: any) {
    if (!USED_COMBINATIONS[name])
        return;

    const index = USED_COMBINATIONS[name].indexOf(adapter);
    USED_COMBINATIONS[name].splice(index, 1);
}


/**
 * validates and inserts the password-hash
 * to ensure there is/was no other instance with a different password
 */
export function _preparePasswordHash(
    rxDatabase: RxDatabase
): Promise<boolean> {
    if (!rxDatabase.password) return Promise.resolve(false);

    const pwHash = hash(rxDatabase.password);

    return (rxDatabase._adminPouch as any).get('_local/pwHash')
        .catch(() => null)
        .then((pwHashDoc: any) => {

            /**
             * if pwHash was not saved, we save it,
             * this operation might throw because another instance runs save at the same time,
             * also we do not await the output because it does not mather
             */
            if (!pwHashDoc) {
                (rxDatabase._adminPouch as any).put({
                    _id: '_local/pwHash',
                    value: pwHash
                }).catch(() => null);
            }

            // different hash was already set by other instance
            if (pwHashDoc && rxDatabase.password && pwHash !== pwHashDoc.value) {
                return rxDatabase.destroy().then(() => {
                    throw newRxError('DB1', {
                        passwordHash: hash(rxDatabase.password),
                        existingPasswordHash: pwHashDoc.value
                    });
                });
            }
            return true;
        });
}


/**
 * to not confuse multiInstance-messages with other databases that have the same
 * name and adapter, but do not share state with this one (for example in-memory-instances),
 * we set a storage-token and use it in the broadcast-channel
 */
export function _ensureStorageTokenExists(rxDatabase: RxDatabase): Promise<string> {
    return (rxDatabase._adminPouch as any).get('_local/storageToken')
        .catch(() => {
            // no doc exists -> insert
            return (rxDatabase._adminPouch as any).put({
                _id: '_local/storageToken',
                value: randomToken(10)
            })
                .catch(() => { })
                .then(() => promiseWait(0));
        })
        .then(() => (rxDatabase._adminPouch as any).get('_local/storageToken'))
        .then((storageTokenDoc2: any) => storageTokenDoc2.value);
}


/**
 * writes the changeEvent to the broadcastChannel
 */
export function writeToSocket(
    rxDatabase: RxDatabase,
    changeEvent: RxChangeEvent
): Promise<boolean> {
    if (
        rxDatabase.multiInstance &&
        !changeEvent.isIntern() &&
        rxDatabase.broadcastChannel
    ) {

        const socketDoc = changeEvent.toJSON();
        delete socketDoc.db;
        const sendOverChannel = {
            db: rxDatabase.token, // database-token
            st: rxDatabase.storageToken, // storage-token
            d: socketDoc
        };
        return rxDatabase.broadcastChannel
            .postMessage(sendOverChannel)
            .then(() => true);
    } else
        return Promise.resolve(false);
}


/**
 * returns the primary for a given collection-data
 * used in the internal pouchdb-instances
 */
export function _collectionNamePrimary(name: string, schema: RxJsonSchema) {
    return name + '-' + schema.version;
}


/**
 * removes all internal docs of a given collection
 * @return resolves all known collection-versions
 */
export function _removeAllOfCollection(
    rxDatabase: RxDatabase,
    collectionName: string
): Promise<number[]> {

    return rxDatabase.lockedRun(
        () => (rxDatabase._collectionsPouch as any).allDocs({
            include_docs: true
        })
    ).then((data: any) => {
        const relevantDocs = data.rows
            .map((row: any) => row.doc)
            .filter((doc: any) => {
                const name = doc._id.split('-')[0];
                return name === collectionName;
            });
        return Promise.all(
            relevantDocs
                .map((doc: any) => rxDatabase.lockedRun(
                    () => (rxDatabase._collectionsPouch as any).remove(doc)
                ))
        ).then(() => relevantDocs.map((doc: any) => doc.version));
    });
}


function _prepareBroadcastChannel(rxDatabase: RxDatabase) {
    // broadcastChannel
    rxDatabase.broadcastChannel = new BroadcastChannel(
        'RxDB:' +
        rxDatabase.name + ':' +
        'socket'
    );
    rxDatabase.broadcastChannel$ = new Subject();
    rxDatabase.broadcastChannel.onmessage = msg => {
        if (msg.st !== rxDatabase.storageToken) return; // not same storage-state
        if (msg.db === rxDatabase.token) return; // same db
        const changeEvent = changeEventfromJSON(msg.d);
        (rxDatabase.broadcastChannel$ as any).next(changeEvent);
    };

    // TODO only subscribe when sth is listening to the event-chain
    rxDatabase._subs.push(
        rxDatabase.broadcastChannel$.subscribe(cE => {
            rxDatabase.$emit(cE);
        })
    );
}


/**
 * do the async things for this database
 */
function prepare(rxDatabase: RxDatabase): Promise<void> {
    rxDatabase._adminPouch = _internalAdminPouch(rxDatabase.name, rxDatabase.adapter, rxDatabase.pouchSettings);
    rxDatabase._collectionsPouch = _internalCollectionsPouch(rxDatabase.name, rxDatabase.adapter, rxDatabase.pouchSettings);

    // ensure admin-pouch is useable
    return rxDatabase._adminPouch.info().then(() => {
        // validate/insert password-hash
        return Promise.all([
            _ensureStorageTokenExists(rxDatabase),
            _preparePasswordHash(rxDatabase)
        ]);
    }).then(([storageToken]) => {
        rxDatabase.storageToken = storageToken;
        if (rxDatabase.multiInstance) {
            _prepareBroadcastChannel(rxDatabase);
        }
    });
}


export function create<Collections = { [key: string]: RxCollection }>({
    name,
    adapter,
    password,
    multiInstance = true,
    queryChangeDetection = false,
    ignoreDuplicate = false,
    options = {},
    pouchSettings = {}
}: RxDatabaseCreator): Promise<RxDatabase<Collections>> {
    validateCouchDBString(name);

    // check if pouchdb-adapter
    if (typeof adapter === 'string') {
        // TODO make a function hasAdapter()
        if (!(PouchDB as any).adapters || !(PouchDB as any).adapters[adapter]) {
            throw newRxError('DB9', {
                adapter
            });
        }
    } else {
        isLevelDown(adapter);
        if (!(PouchDB as any).adapters || !(PouchDB as any).adapters.leveldb) {
            throw newRxError('DB10', {
                adapter
            });
        }
    }

    if (password) {
        overwritable.validatePassword(password);
    }

    // check if combination already used
    if (!ignoreDuplicate) {
        _isNameAdapterUsed(name, adapter);
    }

    // add to used_map
    if (!USED_COMBINATIONS[name])
        USED_COMBINATIONS[name] = [];
    USED_COMBINATIONS[name].push(adapter);

    const db = new RxDatabaseBase(
        name,
        adapter,
        password,
        multiInstance,
        queryChangeDetection,
        options,
        pouchSettings
    );

    return prepare(db as any)
        .then(() => {
            runPluginHooks('createRxDatabase', db);
            return db;
        }) as any;
}


export function getPouchLocation(
    dbName: string,
    collectionName: string,
    schemaVersion: number
) {
    const prefix = dbName + '-rxdb-' + schemaVersion + '-';
    if (!collectionName.includes('/')) {
        return prefix + collectionName;
    } else {
        // if collectionName is a path, we have to prefix the last part only
        const split = collectionName.split('/');
        const last = split.pop();

        let ret = split.join('/');
        ret += '/' + prefix + last;
        return ret;
    }
}


function _spawnPouchDB(
    dbName: string,
    adapter: any,
    collectionName: string,
    schemaVersion: number,
    pouchSettings: PouchSettings = {},
    pouchSettingsFromRxDatabaseCreator: PouchSettings = {}
): PouchDBInstance {
    const pouchLocation = getPouchLocation(dbName, collectionName, schemaVersion);
    const pouchDbParameters = {
        location: pouchLocation,
        adapter: adapterObject(adapter),
        settings: pouchSettings
    };
    const pouchDBOptions = Object.assign({},
        pouchDbParameters.adapter,
        pouchSettingsFromRxDatabaseCreator,
        pouchDbParameters.settings
    );
    runPluginHooks('preCreatePouchDb', pouchDbParameters);
    return new PouchDB(
        pouchDbParameters.location,
        pouchDBOptions
    ) as any;
}


function _internalAdminPouch(
    name: string,
    adapter: any,
    pouchSettingsFromRxDatabaseCreator: PouchSettings = {}
) {
    return _spawnPouchDB(
        name,
        adapter,
        '_admin',
        0, {
        // no compaction because this only stores local documents
        auto_compaction: false,
        revs_limit: 1
    },
        pouchSettingsFromRxDatabaseCreator
    );
}


function _internalCollectionsPouch(
    name: string,
    adapter: any,
    pouchSettingsFromRxDatabaseCreator: PouchSettings = {}
) {
    return _spawnPouchDB(
        name,
        adapter,
        '_collections', 0,
        {
            // no compaction because this only stores local documents
            auto_compaction: false,
            revs_limit: 1
        },
        pouchSettingsFromRxDatabaseCreator
    );
}


/**
 * removes the database and all its known data
 */
export function removeDatabase(
    databaseName: string,
    adapter: any
): Promise<any> {
    const adminPouch = _internalAdminPouch(databaseName, adapter);
    const collectionsPouch = _internalCollectionsPouch(databaseName, adapter);

    return collectionsPouch.allDocs({
        include_docs: true
    })
        // remove collections
        .then(collectionsData => Promise.all(
            collectionsData.rows
                .map((colDoc: any) => colDoc.id)
                .map((id: string) => {
                    const split = id.split('-');
                    const name = split[0];
                    const version = parseInt(split[1], 10);
                    const pouch = _spawnPouchDB(databaseName, adapter, name, version);
                    return pouch.destroy();
                })
        ))
        // remove internals
        .then(() => Promise.all([
            collectionsPouch.destroy(),
            adminPouch.destroy()
        ]));
}


/**
 * check is the given adapter can be used
 */
export function checkAdapter(adapter: any): Promise<boolean> {
    return overwritable.checkAdapter(adapter);
}


export function isInstanceOf(obj: any) {
    return obj instanceof RxDatabaseBase;
}


export function dbCount(): number {
    return DB_COUNT;
}


cEvent => isInstanceOfRxChangeEvent(cEvent)


(docsRes: any) => {
                return Promise.all(
                    docsRes.rows
                        .map((row: any) => ({
                            _id: row.key,
                            _rev: row.value.rev
                        }))
                        .map((doc: any) => colPouch.remove(doc._id, doc._rev))
                );
            }


(row: any) => ({
                            _id: row.key,
                            _rev: row.value.rev
                        })


(doc: any) => colPouch.remove(doc._id, doc._rev)


(doc: any) => this.lockedRun(
                () => (this._collectionsPouch as any).remove(doc)
            )


() => (this._collectionsPouch as any).remove(doc)


() => (this._collectionsPouch as any).get(internalPrimary)


(collectionDoc: any) => {
                colDoc = collectionDoc;

                if (collectionDoc && collectionDoc.schemaHash !== schemaHash) {
                    // collection already exists with different schema, check if it has documents
                    const pouch = this._spawnPouchDB(args.name, args.schema.version, args.pouchSettings);
                    return pouch.find({
                        selector: {
                            _id: {}
                        },
                        limit: 1
                    }).then(oneDoc => {
                        if (oneDoc.docs.length !== 0) {
                            // we have one document
                            throw newRxError('DB6', {
                                name: args.name,
                                previousSchemaHash: collectionDoc.schemaHash,
                                schemaHash
                            });
                        }
                        return collectionDoc;
                    });
                } else return collectionDoc;
            }


oneDoc => {
                        if (oneDoc.docs.length !== 0) {
                            // we have one document
                            throw newRxError('DB6', {
                                name: args.name,
                                previousSchemaHash: collectionDoc.schemaHash,
                                schemaHash
                            });
                        }
                        return collectionDoc;
                    }


() => createRxCollection(args as any)


(collection: any) => {
                col = collection;
                if (
                    Object.keys(collection.schema.encryptedPaths).length > 0 &&
                    !this.password
                ) {
                    throw newRxError('DB7', {
                        name: args.name
                    });
                }

                if (!colDoc) {
                    return this.lockedRun(
                        () => (this._collectionsPouch as any).put({
                            _id: internalPrimary,
                            schemaHash,
                            schema: collection.schema.normalized,
                            version: collection.schema.version
                        })
                    ).catch(() => { });
                }
            }