import moment from 'moment';

interface FieldValueBuilder {
  readonly build: (field: Api.SingleTableField, params: any) => any;
}

class DefaultBuilder implements FieldValueBuilder {
  readonly build = (field: Api.SingleTableField, params: any) => {
    const value = params ? params[field.code] : null;
    return value;
  };
}

class TextBuilder implements FieldValueBuilder {
  readonly build = (field: Api.SingleTableField, params: any) => {
    const value = params ? params[field.code] : '';
    return value || '';
  };
}

class BooleanSelectBuilder implements FieldValueBuilder {
  readonly build = (field: Api.SingleTableField, params: any) => {
    const value = params ? params[field.code] : false;
    return value || false;
  };
}

class IdEntityBuilder implements FieldValueBuilder {
  readonly build = (field: Api.SingleTableField, params: any) => {
    const ety = params ? params[field.code] : undefined;
    const value = ety ? ety.id : '';
    return value || '';
  };
}

class DateRangeBuilder implements FieldValueBuilder {
  readonly build = (field: Api.SingleTableField, params: any) => {
    const value = params ? params[field.code] : undefined;
    return value ? moment(value) : undefined;
  };
}

class DateTimeRangeBuilder implements FieldValueBuilder {
  readonly build = (field: Api.SingleTableField, params: any) => {
    const value = params ? params[field.code] : '';
    return value ? moment(value) : undefined;
  };
}

class FieldValueBuilderManager {
  readonly map: Map<string, FieldValueBuilder> = new Map([
    ['default', new DefaultBuilder()],
    ['text.string', new TextBuilder()],
    ['text.id', new TextBuilder()],
    ['select.boolean', new BooleanSelectBuilder()],
    ['id.entity', new IdEntityBuilder()],
    ['dateRange.date', new DateRangeBuilder()],
    ['dateTimeRange.datetime', new DateTimeRangeBuilder()],
  ]);
  readonly defaultBuilder = new DefaultBuilder();

  build(mode: 'create' | 'edit', singleTable: Api.SingleTable, params: any = undefined) {
    const fieldValues: any = new Object();
    let fields: Api.SingleTableField[];
    if (mode === 'edit') {
      fields = singleTable.fields.filter((f) => !!!f.hideInEditForm);
    } else {
      fields = singleTable.fields.filter((f) => !!!f.hideInCreateForm);
    }
    fields.forEach((f) => {
      fieldValues[f.code] = this.buildField(f, params);
    });
    return fieldValues;
  }

  private buildField(field: Api.SingleTableField, params: any) {
    const builder = this.map.get(field.valueType);
    if (builder) {
      return builder.build(field, params);
    }
    return this.defaultBuilder.build(field, params);
  }
}

const fieldValueBuilderManager = new FieldValueBuilderManager();

export default fieldValueBuilderManager;
