<commit_before>import { NgForOfContext } from '@angular/common';
import {
  DefaultIterableDiffer,
  Directive,
  EmbeddedViewRef,
  Input,
  OnChanges,
  TemplateRef,
  ViewContainerRef
} from '@angular/core';

import { DatepickerSelect } from '../selection/base.select';

// TODO remove differ, force the usage of immutable Date and do a simple loop over new value should be enough here

export class DateNavigator {
  constructor(public months: Date[] = []) {}

  moveMonth(amount: number, monthDate?: Date) {
    if (amount === 0)
      return this.months;

      return this.changeMonth(date => new Date(date.getFullYear(), date.getMonth() + amount), monthDate);
  }

  moveYear(amount: number, monthDate?: Date) {
    if (amount === 0)
      return this.months;

    return this.changeMonth(date => new Date(date.getFullYear() + amount, date.getMonth()), monthDate);
  }

  toMonth(month: number, monthDate?: Date) {
    if ( month < 0 || month > 11 ||
      monthDate === undefined ? this.months.every(d => d.getMonth() === month) : month === monthDate.getMonth())
      return this.months;

    return this.changeMonth(date => new Date(date.getFullYear(), month), monthDate);
  }

  toYear(year: number, monthDate?: Date) {
    if ( monthDate === undefined ? this.months.every(d => d.getFullYear() === year) : year === monthDate.getFullYear())
      return this.months;

    return this.changeMonth(date => new Date(year, date.getMonth()), monthDate);
  }

  private changeMonth(mapFn: (date: Date) => Date, monthDate?: Date) {
    const isMonthUndefined = monthDate === undefined;
    return this.months.map( (d, i) =>
      isMonthUndefined || d === monthDate ? mapFn(d) : d
    );
  }
}

export class MonthContext extends NgForOfContext<Date> {

  navigator = new DateNavigator();

  constructor($implicit: Date, public selector: DatepickerSelect<any>) {
     super($implicit, null!, -1, -1);
  }

  get count() { return (<Date[]>this.ngForOf).length; }

  set count(c: number) { /* noop, only avoiding error from NgForOfContext */ }

  setMonths(months: Date[]) {
    this.navigator.months = this.ngForOf = months;
  }
}

@Directive({
  selector: '[forMonth][forMonthOf]'
})
export class ForMonthOf implements OnChanges {

  @Input('forMonthOf') months: Date[] | null | undefined;

  private differ = new DefaultIterableDiffer<Date>(index => index)

  constructor(private template: TemplateRef<MonthContext>, private viewContainer: ViewContainerRef, private select: DatepickerSelect<any>) {}

  ngOnChanges() {
    const changes = this.differ.diff(this.months!);
    if (changes) {
      changes.forEachOperation( (record, adjustedPreviousIndex, currentIndex) => {
        // added
        if (record.previousIndex === null) {
          this.viewContainer.createEmbeddedView(
              this.template, this.newContext(record.item) );
        }
        // removed
        else if (currentIndex === null) {
          this.viewContainer.remove(adjustedPreviousIndex!);
        }
        // moved<commit_msg>refactor: sligtlhy changed DateNavigator<commit_after>import { NgForOfContext } from '@angular/common';
import {
  DefaultIterableDiffer,
  Directive,
  EmbeddedViewRef,
  Input,
  OnChanges,
  TemplateRef,
  ViewContainerRef
} from '@angular/core';

import { DatepickerSelect } from '../selection/base.select';

export class DateNavigator {
  constructor(public months: Date[] = []) {}

  shiftMonth(amount: number, idx?: number) {
    if (amount === 0)
      return this.months;

      return this.changeMonths(date => new Date(date.getFullYear(), date.getMonth() + amount), idx);
  }

  shiftYear(amount: number, idx?: number) {
    if (amount === 0)
      return this.months;

    return this.changeMonths(date => new Date(date.getFullYear() + amount, date.getMonth()), idx);
  }

  toMonth(month: number, idx: number) {
    if ( month >= 0 && month < 12) {
      const currentMonth = this.months[idx];
      if (currentMonth !== undefined && currentMonth.getMonth() !== month) {
        return this.changeMonths(date => new Date(date.getFullYear(), month), idx);
      }
    }

    return this.months;
  }

  toYear(year: number, idx: number) {
    const currentMonth = this.months[idx];
    if ( currentMonth !== undefined && currentMonth.getFullYear() !== year) {
      return this.changeMonths(date => new Date(year, date.getMonth()), idx);
    }

    return this.months;
  }

  private changeMonths(mapFn: (date: Date) => Date, idx?: number) {
    return this.months.map( (d, i) =>
      idx === undefined || i === idx ? mapFn(d) : d
    );
  }
}

export class MonthContext extends NgForOfContext<Date> {

  navigator = new DateNavigator();

  constructor($implicit: Date, public selector: DatepickerSelect<any>) {
     super($implicit, null!, -1, -1);
  }

  get count() { return (<Date[]>this.ngForOf).length; }

  set count(c: number) { /* noop, only avoiding error from NgForOfContext */ }

  setMonths(months: Date[]) {
    this.navigator.months = this.ngForOf = months;
  }
}

// TODO remove differ, force the usage of immutable Date and do a simple loop over new value should be enough here

@Directive({
  selector: '[forMonth][forMonthOf]'
})
export class ForMonthOf implements OnChanges {

  @Input('forMonthOf') months: Date[] | null | undefined;

  private differ = new DefaultIterableDiffer<Date>(index => index)

  constructor(private template: TemplateRef<MonthContext>, private viewContainer: ViewContainerRef, private select: DatepickerSelect<any>) {}

  ngOnChanges() {
    const changes = this.differ.diff(this.months!);
    if (changes) {
      changes.forEachOperation( (record, adjustedPreviousIndex, currentIndex) => {
        // added
        if (record.previousIndex === null) {
          this.viewContainer.createEmbeddedView(
              this.template, this.newContext(record.item) );
        }
        // removed
        else if (currentIndex === null) {
          this.viewContainer.remove(adjustedPreviousIndex!);
        }
        // moved
{'fraction_non_alphanumeric': 0.13833333333333334, 'fraction_numerical': 0.0023333333333333335, 'mean_word_length': 3.4917664670658684, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1516112', 'n_tokens_mistral': 1843, 'n_tokens_neox': 1764, 'n_words': 454}