import path from 'path';
export { default as find } from './find';

class File {
  private _location: string;
  private _root: string;
  private _lines: {
    [index: number]: string;
    length: number;
  };
  private _original: {
    [index: number]: string;
  };
  private _changes: number[] = [];

  constructor(location: string, content: string, root: string = process.cwd()) {
    this._location = location;
    this._root = root;
    
    const lines = content.split('\n').reduce((output, content, index) => ({
      ...output,
      [index]: content,
    }), {});

    this._original = {...lines};

    const lineProxy = new Proxy(lines, {
      get: (prop: {[index: number]: string}, target: number | string) => {
        if (target === 'length') {
          return Object.keys(prop).length;
        }
        return prop[target as number];
      },
      set: (prop: {[index: number]: string}, target: number, value: string) => {
        const descriptor = Object.getOwnPropertyDescriptor(prop, target);
        if (!descriptor) {
          throw new Error('Can not set non existing key');
        }
        if (!this._changes.find(i => i === target)) {
          this._changes.push(target);
        }
        prop[target] = value;
        return true;
      },
    });

    this._lines = lineProxy as any;
  }

  get indexes() {
    return Object.keys(this._lines).map(i => parseInt(i));
  }

  get changed() {
    return this._changes.length > 0;
  }

  get location() {
    return this._location;
  }

  get original() {
    return {...this._original};
  }

  get lines() {
    return this._lines;
  }

  get changes() {
    return [...this._changes];
  }

  get relativeLocation() {
    return path.relative(this._root, this._location);
  }

  toString() {
    const indexes = Object.keys(this._lines);
    const lines = indexes.reduce<string[]>((output, index) => {
      const int = parseInt(index);
      output[int] = this._lines[int];
      return output;
    }, []);
    return lines.filter(l => l).join('\n');
  }
}

export default File;