import {UrlMatcher, UrlSegment} from "@angular/router";

export class HelperFunctions {

  public static scroll(smooth: boolean = false) {
    HelperFunctions.scrollTo(0,0);
  }
  
  public static scrollTo(x,y, smooth: boolean = false) {
    if (typeof document !== 'undefined') {
      if(!smooth) {
        window.scrollTo(x, y);
      } else {
        window.scrollTo({
          top: 0,
          left: 0,
          behavior: "smooth"
        })
      }
    }
  }

  public static scrollToId(elementId:string) {
    if (typeof document !== 'undefined' && document.getElementById(elementId)) {
      document.getElementById(elementId).scrollIntoView({behavior: "smooth"});
    }
  }
  
  public static copy(obj: any): any {
    let copy;

    // Handle the 3 simple types, and null or undefined
    if (null == obj || "object" != typeof obj) return obj;

    // Handle Date
    if (obj instanceof Date) {
      copy = new Date();
      copy.setTime(obj.getTime());
      return copy;
    }

    // Handle Array
    if (obj instanceof Array) {
      copy = [];
      for (let i = 0, len = obj.length; i < len; i++) {
        copy[i] = HelperFunctions.copy(obj[i]);
      }
      return copy;
    }

    // Handle Map
    if (obj instanceof Map) {
      return new Map(obj.entries());
    }

    // Handle Object
    if (obj instanceof Object) {
      copy = {};
      for (let attr in obj) {
        if (obj.hasOwnProperty(attr)) {
          copy[attr] = HelperFunctions.copy(obj[attr]);
        }
      }
      return copy;
    }
    throw new Error("Unable to copy obj! Its type isn't supported.");
  }
  
  public static equals(object1, object2) {
    return object1 === object2 || JSON.stringify(object1) === JSON.stringify(object2);
  }

  public static encodeArray(elements: string[]): string[] {
    let encoded: string[] = [];
    elements.forEach(element => {
      encoded.push(encodeURIComponent(element));
    });
    return encoded;
  }
  
  public static getValues(value: any): any[] {
    return Object.keys(value).map(key => value[key]);
  }

	public static getVocabularyLabel(value: any, vocabulary: any, returnIfNotFound: boolean = true) {
    if(value == undefined || value == null) {
      return null;
    }
		if(vocabulary && value in vocabulary) {
			return vocabulary[value];
		}
    if(returnIfNotFound) {
      return value;
    }
    return null;
	}

  public static sortSDGs(sgd1: string, sdg2: string): number {
    let splitA: string[] = sgd1.split(".");
    let numA: number;
    if(splitA && splitA.length > 0) {
      numA = +splitA[0];
    }
    let splitB: string[] = sdg2.split(".");
    let numB: number;
    if(splitB && splitB.length > 0) {
      numB = +splitB[0];
    }

    if(numA && numB) {
      return numA - numB;
    } else {
      return sgd1.localeCompare(sdg2);
    }
  }
  
  public static swap(array: any[], from, to) {
    array.splice(to, 0, array.splice(from, 1)[0]);
  }
  
  public static routingMatcher:((paths: string[]) => UrlMatcher) = (paths: string[]) => {
    return (segments) => {
      const matchingPathIndex = paths.findIndex((path, index) => {
        const pathSegments = path.split("/");
        return segments.every((segment, i) =>
          pathSegments.length > i && (
            pathSegments[i].startsWith(":") ? true : segment.path.toLowerCase() === pathSegments[i].toLowerCase()));
      });
      
      if (matchingPathIndex >= 0) {
        const matchingPath = paths[matchingPathIndex];
        
        const consumed: UrlSegment[] = [];
        const params = {};
        
        matchingPath.split("/").forEach((path, i) => {
          consumed.push(segments[i]);
          if (path.startsWith(":")) {
            const param = path.substring(1);
            params[param] = segments[i];
          }
        });
        
        return {
          consumed: consumed,
          posParams: params
        };
      }
      
      return null;
    };
  };
}
