<mat-spinner style="margin:0 auto;" mode="indeterminate" class="big-spinner-center"
  [style.display]="showBigSpinner ? 'block' : 'none'">
</mat-spinner>

<div class="container">
  <h1> Create new configuration </h1>

  <mat-card class="wizard-container">
    <mat-horizontal-stepper #stepper>
      <mat-step [stepControl]="firstFormGroup" [completed]="false">
        <p class="required">
          <a class="mat-form-field-required-marker">*</a> - required field
        </p>
        <h2>Model</h2>
        <form [formGroup]="firstFormGroup">
          <mat-card>
            <ng-template matStepLabel>Select model and precision</ng-template>

            <span class="spinner-wrapper">
              <mat-form-field class="form-field long" appearance="outline">
                <mat-label>model</mat-label>
                <input required formControlName="modelLocation" matInput>
              </mat-form-field>
              <button id="choose-file-btn" mat-raised-button color="primary" class="fixed-height choose-file-btn"
                (click)="openDialog('modelLocation', 'models')">
                <img class="icon" src="./../../assets/145b-document-outlined-white.svg">
                Choose file
              </button>
              <button id="show-graph-btn" *ngIf="showGraphButton" mat-raised-button color="accent" class="fixed-height"
                (click)="showGraph()">
                <img class="icon" src="./../../assets/298a-workflow-process-solid.svg">
                Show graph
              </button>
              <mat-spinner *ngIf="showGraphSpinner || showSpinner" class="spinner" [diameter]="25"></mat-spinner>
            </span>

            <div *ngIf="boundaryNodesVisible()">
              <ng-container *ngIf="boundaryNodes.inputs === 'select'">
                <mat-form-field class="form-field" appearance="outline">
                  <mat-label>graph input <a class="mat-form-field-required-marker">*</a></mat-label>
                  <mat-select formControlName="input" multiple>
                    <mat-option *ngFor="let input of inputs" [value]="input"
                      [ngClass]="input === 'custom' ? 'custom-option' : null"
                      [disabled]="order['input'][0] === 'custom' && input !== 'custom'"
                      (onSelectionChange)="boundaryNodesChanged($event.source.value, 'input')">
                      {{ input === 'custom' ? '(Add your custom input node)' : input }}
                      {{ inputs.length > 1 && order['input'].indexOf(input) !== -1 && input !== 'custom' ?
                      '(' + (order['input'].indexOf(input) + 1) + ')' : null }}
                    </mat-option>
                  </mat-select>
                </mat-form-field>
              </ng-container>
              <ng-container *ngIf="boundaryNodes.inputs === 'custom'">
                <mat-form-field class="form-field" appearance="outline">
                  <mat-label>graph input <a class="mat-form-field-required-marker">*</a></mat-label>
                  <input formControlName="input" matInput>
                </mat-form-field>
              </ng-container>
              <ng-container *ngIf="boundaryNodes.outputs === 'select'">
                <mat-form-field class="form-field" appearance="outline">
                  <mat-label>graph output <a class="mat-form-field-required-marker">*</a></mat-label>
                  <mat-select formControlName="output" multiple>
                    <mat-option *ngFor="let output of outputs" [value]="output"
                      [ngClass]="output === 'custom' ? 'custom-option' : null"
                      [disabled]="order['output'][0] === 'custom' && output !== 'custom'"
                      (onSelectionChange)="boundaryNodesChanged($event.source.value, 'output')">
                      {{ output === 'custom' ? '(Add your custom output node)' : output }}
                      {{ outputs.length > 1 && order['output'].indexOf(output) !== -1 && output !== 'custom' ?
                      '(' + (order['output'].indexOf(output) + 1) + ')' : null }}
                    </mat-option>
                  </mat-select>
                </mat-form-field>
                <ng-container
                  *ngIf="firstFormGroup.get('output').value.length === 1 && firstFormGroup.get('output').value[0] === 'custom'">
                  <mat-form-field class="form-field" appearance="outline"
                    matTooltip="Multiple custom nodes should be separated by comma">
                    <mat-label>graph output <a class="mat-form-field-required-marker">*</a></mat-label>
                    <input formControlName="outputOther" matInput>
                  </mat-form-field>
                </ng-container>
              </ng-container>
              <ng-container *ngIf="boundaryNodes.outputs === 'custom'">
                <mat-form-field class="form-field" appearance="outline">
                  <mat-label>graph output <a class="mat-form-field-required-marker">*</a></mat-label>
                  <input formControlName="output" matInput>
                </mat-form-field>
              </ng-container>
              <br>
              <a *ngIf="boundaryNodesVisible()" class="info">
                Order of the inputs and outputs matters.
              </a>
            </div>
          </mat-card>

          <ng-container *ngIf="firstFormGroup.get('framework').value">
            <h2>Model domain</h2>
            <mat-card>
              <div class="spinner-wrapper">
                <mat-form-field class="form-field" appearance="outline">
                  <mat-label>model domain</mat-label>
                  <mat-select formControlName="modelDomain" required>
                    <mat-option *ngFor="let domain of domains" [value]="domain.name" matTooltipPosition="right"
                      [matTooltip]="domain.help">
                      <ng-container *ngIf="domain.name === 'nlp'">NLP</ng-container>
                      <ng-container *ngIf="domain.name !== 'nlp'">{{ domain.name | modelList | titlecase }}
                      </ng-container>
                    </mat-option>
                  </mat-select>
                </mat-form-field>
                <mat-spinner class="spinner" *ngIf="showDomainSpinner" [diameter]="25"></mat-spinner>
              </div>
            </mat-card>
          </ng-container>
        </form>

        <ng-container *ngIf="precisions.length > 1">
          <h2>Precision</h2>
          <mat-card>
            <p>Please refer to
              <a href="https://software.intel.com/content/www/us/en/develop/articles/intel-sdm.html" target="_blank">
                Intel Software Developer Manuals</a>
              for precision support.
            </p>
            <div class="custom-slider">
              <ngx-slider [(value)]="precisionIndex" [options]="sliderOptions"></ngx-slider>
            </div>
            <h2>
              <mat-checkbox [(ngModel)]="precisions[precisionIndex].name !== 'fp32' ? tuningEnabled : tuningDisabled"
                [ngModelOptions]="{standalone: true}" [disabled]="precisions[precisionIndex].name === 'fp32'"
                (change)="onTuningEnabledChange()" matTooltip="Enable/disable tuning" class="tuning-checkbox">
                Run tuning
              </mat-checkbox>
            </h2>
          </mat-card>
        </ng-container>

        <br />
        <div class="float-right">
          <button mat-raised-button matStepperNext>
            <img class="navigation-icon" src="./../../assets/083-arrow-forward-right.svg">
            Next
          </button>
        </div>
      </mat-step>

      <mat-step [stepControl]="secondFormGroup" [completed]="false">
        <ng-template matStepLabel>Set configuration</ng-template>

        <form [formGroup]="secondFormGroup">

          <h2>Evaluation</h2>
          <mat-card>
            <span class="inline">
              <mat-form-field class="form-field" appearance="outline">
                <mat-label>evaluation dataset type</mat-label>
                <mat-select formControlName="dataLoaderEvaluation"
                  (selectionChange)="setDefaultDataLoaderParam($event, 'evaluation')">
                  <mat-option *ngFor="let dataLoader of dataLoaders" [value]="dataLoader.name"
                    matTooltipPosition="right" [ngClass]="dataLoader.name === 'custom' ? 'custom-option' : null"
                    [matTooltip]="dataLoader.help">
                    {{ dataLoader.name === 'custom' ? '(Add your custom data loader)' : dataLoader.name }}
                  </mat-option>
                </mat-select>
              </mat-form-field>
            </span>
            <span *ngIf="showDatasetLocation['evaluation']" class="inline">
              <mat-form-field class="form-field long" appearance="outline">
                <mat-label>dataset location <a class="mat-form-field-required-marker">*</a></mat-label>
                <input formControlName="datasetLocationEvaluation" matInput>
              </mat-form-field>
              <button id="choose-dataset-btn" mat-raised-button color="primary" class="browse choose-file-btn"
                (click)="openDialog('datasetLocationEvaluation', 'datasets', 'datasetLocation')">
                <img class="icon" src="./../../assets/050a-folder-solid-white.svg">
                Choose dataset
              </button>
              <mat-checkbox *ngIf="precisions[precisionIndex] && precisions[precisionIndex].name === 'int8'"
                [checked]="true" (change)="calibrationDataChange($event.checked)" class="checkbox">
                Use the same data as calibration
              </mat-checkbox>
            </span>
            <br />
            <span class="inline">
              <ng-container *ngFor="let param of dataLoaderParams['evaluation']">
                <ng-container *ngIf="param.name !== 'root'">
                  <mat-form-field class="form-field" appearance="outline">
                    <mat-label>{{ param.label || param.name }}</mat-label>
                    <input [(ngModel)]="param.value" matInput [ngModelOptions]="{standalone: true}"
                      matTooltipPosition="right" [matTooltip]="param.help">
                  </mat-form-field>
                  <button id="choose-eval-btn" *ngIf="fileBrowserParams.includes(param.name)" mat-raised-button
                    color="primary" class="browse choose-file-btn"
                    (click)="openDialog(param.name, 'all', 'evaluation')">
                    <img class="icon" src="./../../assets/050a-folder-solid-white.svg">
                    Choose file
                  </button>
                </ng-container>
              </ng-container>
            </span>
            <br>
            <a *ngIf="secondFormGroup.get('dataLoaderEvaluation').value === 'custom'" class="custom">
              Fill the code template before tuning
            </a>

            <ng-container *ngIf="tuningEnabled && !useEvaluationData && precisions[precisionIndex].name === 'int8'">
              <span class="inline">
                <mat-form-field class="form-field" appearance="outline">
                  <mat-label>calibration dataset type</mat-label>
                  <mat-select formControlName="dataLoaderQuantization"
                    (selectionChange)="setDefaultDataLoaderParam($event, 'quantization')">
                    <mat-option *ngFor="let dataLoader of dataLoaders" [value]="dataLoader.name"
                      matTooltipPosition="right" [ngClass]="dataLoader.name === 'custom' ? 'custom-option' : null"
                      [matTooltip]="dataLoader.help">
                      {{ dataLoader.name === 'custom' ? '(Add your custom data loader)' : dataLoader.name }}
                    </mat-option>
                  </mat-select>
                </mat-form-field>
              </span>
              <span *ngIf="showDatasetLocation['quantization']" class="inline">
                <mat-form-field class="form-field long" appearance="outline">
                  <mat-label>dataset location <a class="mat-form-field-required-marker">*</a></mat-label>
                  <input formControlName="datasetLocationQuantization" matInput (change)="useForQuantization()">
                </mat-form-field>
                <button id="choose-dataset-quant-btn" mat-raised-button color="primary" class="browse"
                  (click)="openDialog('datasetLocationQuantization', 'datasets')">
                  <img class="icon" src="./../../assets/050a-folder-solid-white.svg">
                  Choose dataset
                </button>
              </span>
              <br />
              <span class="inline">
                <ng-container *ngFor="let param of dataLoaderParams['quantization']">
                  <ng-container *ngIf="param.name !== 'root'">
                    <mat-form-field class="form-field" appearance="outline">
                      <mat-label>{{ param.label || param.name }}</mat-label>
                      <input [(ngModel)]="param.value" matInput [ngModelOptions]="{standalone: true}"
                        matTooltipPosition="right" [matTooltip]="param.help">
                    </mat-form-field>
                    <button id="choose-quant-btn" *ngIf="fileBrowserParams.includes(param.name)" mat-raised-button
                      color="primary" class="browse choose-file-btn"
                      (click)="openDialog(param.name, 'all', 'quantization')">
                      <img class="icon" src="./../../assets/050a-folder-solid-white.svg">
                      Choose file
                    </button>
                  </ng-container>
                </ng-container>
              </span>
              <a *ngIf="secondFormGroup.get('dataLoaderQuantization').value === 'custom'" class="custom">
                Fill the code template before tuning
              </a>
              <br>
            </ng-container>
            <mat-form-field *ngIf="precisions[precisionIndex] && precisions[precisionIndex].name === 'int8'"
              class="form-field" appearance="outline" (change)="updateCalibrationBatchSize()">
              <mat-label>calibration sampling size</mat-label>
              <input formControlName="samplingSize" matInput placeholder="100">
            </mat-form-field>
            <mat-form-field *ngIf="precisions[precisionIndex] && precisions[precisionIndex].name === 'int8'"
              class="form-field" appearance="outline">
              <mat-label>calibration batch size</mat-label>
              <input formControlName="calibrationBatchSize" matInput placeholder="100">
            </mat-form-field>
          </mat-card>

          <ng-container
            *ngIf="secondFormGroup.get('dataLoaderQuantization').value !== 'custom' && secondFormGroup.get('dataLoaderEvaluation').value !== 'custom'">
            <h2>Transforms
              <a href="https://github.com/intel/neural-compressor/blob/master/docs/transform.md" target="_blank">
                <img class="help-icon" src="./../../assets/005a-help-solid.svg"
                  matTooltip="Click to open documentation">
              </a>
            </h2>
            <mat-card>
              <ng-container *ngFor="let transformItem of transformationParams; let index = index; let last = last">
                <span class="inline">
                  <mat-form-field class="form-field" appearance="outline">
                    <mat-label>transform {{ index }}</mat-label>
                    <mat-select [(ngModel)]="transformItem['name']" [ngModelOptions]="{standalone: true}"
                      (selectionChange)="setDefaultTransformationParam($event, index)">
                      <mat-option *ngFor="let transformation of transformations" [value]="transformation.name"
                        [ngClass]="transformation.name === 'custom' ? 'custom-option' : null" matTooltipPosition="right"
                        [matTooltip]="transformation.help">
                        {{ transformation.name === 'custom' ? '(Add your custom transformation)' : transformation.name
                        }}
                      </mat-option>
                    </mat-select>
                  </mat-form-field>
                  <ng-container *ngIf="isArray(transformItem['params'])">
                    <ng-container *ngFor="let param of transformItem['params']; let index = index">
                      <ng-container *ngIf="resizeValues && param.name === 'size'">
                        <mat-form-field class="form-field" appearance="outline">
                          <mat-label>size</mat-label>
                          <mat-select [(ngModel)]="param.value" [ngModelOptions]="{standalone: true}">
                            <mat-option *ngFor="let resizeValue of resizeValues" [value]="resizeValue"
                              matTooltipPosition="right" [ngClass]="resizeValue === 'custom' ? 'custom-option' : null"
                              [matTooltip]="param.help">
                              {{ resizeValue === 'custom' ? '(Add your custom size)' : resizeValue }}
                            </mat-option>
                          </mat-select>
                        </mat-form-field>
                      </ng-container>
                      <mat-form-field *ngIf="resizeValues && param.name === 'size' && param.value === 'custom'"
                        class="form-field" appearance="outline">
                        <mat-label>{{ param.label || param.name }}</mat-label>
                        <input [(ngModel)]="resizeCustom" matInput [ngModelOptions]="{standalone: true}"
                          matTooltipPosition="right" [matTooltip]="param.help">
                      </mat-form-field>
                      <mat-form-field *ngIf="!resizeValues || param.name !== 'size'" class="form-field"
                        appearance="outline">
                        <mat-label>{{ param.label || param.name }}</mat-label>
                        <input [(ngModel)]="param.value" matInput [ngModelOptions]="{standalone: true}"
                          matTooltipPosition="right" [matTooltip]="param.help">
                      </mat-form-field>
                      <button [attr.id]="'choose-tranform-file-btn' + index"
                        *ngIf="fileBrowserParams.includes(param.name)" mat-raised-button color="primary"
                        class="browse choose-file-btn" (click)="openDialog(param.name, 'all', transformItem['params'])">
                        <img class="icon" src="./../../assets/050a-folder-solid-white.svg">
                        Choose file
                      </button>
                    </ng-container>
                  </ng-container>
                  <button id="remove-transform-btn" mat-icon-button color="warn" class="browse"
                    (click)="removeTransformation(index)" matTooltip="Remove this transformation">
                    <img class="icon" src="./../../assets/057b-trash-outlined.svg">
                  </button>
                </span>
                <br *ngIf="!last">
              </ng-container>
              <button id="new-transform-btn" mat-raised-button color="accent" class="browse"
                (click)="addNewTransformation()">
                &#65291; Add new transformation
              </button>
            </mat-card>
          </ng-container>

          <h2>Metric
            <a href="https://github.com/intel/neural-compressor/blob/master/docs/metrics.md" target="_blank">
              <img class="help-icon" src="./../../assets/005a-help-solid.svg" matTooltip="Click to open documentation">
            </a>
          </h2>
          <mat-card>
            <mat-form-field class="form-field" appearance="outline">
              <mat-label>metric</mat-label>
              <mat-select formControlName="metric" (selectionChange)="setDefaultMetricParam($event)">
                <mat-option *ngFor="let metric of metrics" [value]="metric.name" matTooltipPosition="right"
                  [ngClass]="metric.name === 'custom' ? 'custom-option' : null" [matTooltip]="metric.help">
                  {{ metric.name === 'custom' ? '(Add your custom metric)' : metric.name }}
                </mat-option>
              </mat-select>
            </mat-form-field>
            <a *ngIf="secondFormGroup.get('metric').value === 'custom'" class="custom">
              Fill the code template before tuning
            </a>
            <ng-container *ngFor="let param of metricParams">
              <ng-container *ngIf="isArray(param.value)">
                <mat-form-field class="form-field" appearance="outline">
                  <mat-label>{{ param.label || param.name }}</mat-label>
                  <mat-select [(ngModel)]="metricParam" [ngModelOptions]="{standalone: true}">
                    <mat-option *ngFor="let option of param.value" [value]="option">{{ option }}</mat-option>
                  </mat-select>
                </mat-form-field>
              </ng-container>
              <ng-container *ngIf="typeOf(param.value) === 'boolean'">
                <mat-form-field class="form-field" appearance="outline">
                  <mat-label>{{ param.label || param.name }}</mat-label>
                  <mat-select [(ngModel)]="metricParam" [ngModelOptions]="{standalone: true}">
                    <mat-option [value]="true">yes</mat-option>
                    <mat-option [value]="false">no</mat-option>
                  </mat-select>
                </mat-form-field>
              </ng-container>
              <ng-container *ngIf="typeOf(param.value) === 'string'">
                <mat-form-field class="form-field" appearance="outline">
                  <mat-label>{{ param.label || param.name }}</mat-label>
                  <input [(ngModel)]="metricParam" matInput [ngModelOptions]="{standalone: true}"
                    matTooltipPosition="right" [matTooltip]="param.help">
                </mat-form-field>
                <button id="choose-eval-btn" *ngIf="fileBrowserParams.includes(param.name)" mat-raised-button
                  color="primary" class="browse choose-file-btn" (click)="openDialog(param.name, 'all', 'metric')">
                  <img class="icon" src="./../../assets/050a-folder-solid-white.svg">
                  Choose file
                </button>
              </ng-container>
            </ng-container>
          </mat-card>
        </form>
        <br>
        <mat-checkbox [(ngModel)]="showAdvancedParams" [ngModelOptions]="{standalone: true}"
          matTooltip="Show/hide advanced parameters step" class="tuning-checkbox">
          Show advanced parameters
        </mat-checkbox>

        <ng-container *ngIf="showAdvancedParams">
          <h2>Quantization</h2>
          <mat-card>
            <form [formGroup]="secondFormGroup">
              <mat-form-field class="form-field" appearance="outline">
                <mat-label>approach</mat-label>
                <mat-select formControlName="approach">
                  <mat-option *ngFor="let approach of approaches" [value]="approach.name" matTooltipPosition="right"
                    [matTooltip]="approach.help">
                    {{ approach.name }}
                  </mat-option>
                </mat-select>
              </mat-form-field>
            </form>
          </mat-card>

          <ng-container *ngIf="tuningEnabled">
            <h2>Tune</h2>
            <mat-card>
              <form [formGroup]="secondFormGroup">
                <mat-form-field class="form-field" appearance="outline">
                  <mat-label>tuning strategy</mat-label>
                  <mat-select formControlName="strategy">
                    <mat-option *ngFor="let tuning of tunings" [value]="tuning.name" matTooltipPosition="right"
                      [matTooltip]="tuning.help">
                      {{ tuning.name }}
                    </mat-option>
                  </mat-select>
                </mat-form-field>

                <mat-form-field class="form-field" appearance="outline">
                  <mat-label>accuracy goal</mat-label>
                  <input type="number" formControlName="accuracyGoal" matInput>
                </mat-form-field>

                <mat-form-field class="form-field" appearance="outline">
                  <mat-label>objective</mat-label>
                  <mat-select formControlName="objective">
                    <mat-option *ngFor="let objective of objectives" [value]="objective.name" matTooltipPosition="right"
                      [matTooltip]="objective.help">
                      {{ objective.name }}
                    </mat-option>
                  </mat-select>
                </mat-form-field>
                <br>
                <mat-form-field class="form-field" appearance="outline">
                  <mat-label>timeout</mat-label>
                  <input type="number" formControlName="timeout" matInput>
                </mat-form-field>

                <mat-form-field class="form-field" appearance="outline">
                  <mat-label>max trials</mat-label>
                  <input type="number" formControlName="maxTrials" matInput>
                </mat-form-field>

                <mat-form-field class="form-field" appearance="outline">
                  <mat-label>random seed</mat-label>
                  <input type="number" formControlName="randomSeed" matInput>
                </mat-form-field>
              </form>
            </mat-card>
          </ng-container>

          <h2>Benchmarking</h2>
          <form [formGroup]="secondFormGroup">
            <mat-card>
              <form [formGroup]="secondFormGroup">
                <mat-form-field class="form-field" appearance="outline">
                  <mat-label>batch size</mat-label>
                  <input formControlName="batchSize" matInput value="1">
                </mat-form-field>
                <mat-form-field class="form-field" appearance="outline">
                  <mat-label>warmup</mat-label>
                  <input type="number" formControlName="warmup" matInput>
                </mat-form-field>
                <mat-form-field class="form-field" appearance="outline"
                  [matTooltip]="'Default iteration is -1 (iterate all samples)'">
                  <mat-label>iteration</mat-label>
                  <input type="number" formControlName="iteration" matInput>
                </mat-form-field>
                <mat-form-field class="form-field" appearance="outline">
                  <mat-label>cores per instance</mat-label>
                  <input min=1 step=1 type="number" formControlName="cores_per_instance" matInput>
                </mat-form-field>
                <mat-form-field class="form-field" appearance="outline">
                  <mat-label>number of instances</mat-label>
                  <input min=1 step=1 type="number" formControlName="num_of_instance" matInput>
                </mat-form-field>
                <a class="cores-warning" *ngIf="!coresValidated()">
                  <img class="warning-icon" src="./../../assets/006a-alert-solid-red.svg">
                  cores_per_instance * num_of_instance should not be greater than number of cores
                  ({{ secondFormGroup.get('cores_per_instance').value }}
                  * {{ secondFormGroup.get('num_of_instance').value }}
                  > {{ modelService.systemInfo['sockets'] * modelService.systemInfo['cores_per_socket'] }})
                </a>
              </form>
            </mat-card>
          </form>
        </ng-container>
        <br>
        <div class="float-right">
          <button id="finish-adv-btn" mat-raised-button color="accent"
            [disabled]="finishDisabled || firstFormGroup.status === 'INVALID' || secondFormGroup.status === 'INVALID' || !coresValidated()"
            (click)="addModel()" queryParamsHandling="preserve">
            <img class="navigation-icon" src="./../../assets/056a-save-solid-white.svg">
            Finish
          </button>
        </div>
      </mat-step>
    </mat-horizontal-stepper>
  </mat-card>
</div>