/* @flow */

import TypeConstructor from './TypeConstructor';

import type Type from './Type';
import compareTypes from '../compareTypes';

import getErrorMessage from "../getErrorMessage";
import type Validation, {ErrorTuple, IdentifierPath} from '../Validation';

export default class GenericType extends TypeConstructor {

  typeName: string = 'GenericType';

  *errors (validation: Validation<any>, path: IdentifierPath, input: any): Generator<ErrorTuple, void, void> {
    const {name, impl, context} = this;

    if (!(input instanceof impl)) {
      yield [path, getErrorMessage('ERR_EXPECT_INSTANCEOF', name), this];
    }
    else {
      const annotation = context.getAnnotation(impl);
      if (annotation) {
        yield * annotation.errors(validation, path, input);
      }
    }
  }

  accepts <P> (input: any, ...typeInstances: Type<P>[]): boolean {
    const {context, impl} = this;
    if (!(input instanceof impl)) {
      return false;
    }
    const annotation = context.getAnnotation(impl);
    if (annotation) {
      return annotation.accepts(input);
    }
    else {
      return true;
    }
  }

  compareWith <P> (input: Type<any>, ...typeInstances: Type<P>[]): -1 | 0 | 1 {
    const {context, impl} = this;
    const annotation = context.getAnnotation(impl);
    if (annotation) {
      const expected = annotation.unwrap(...typeInstances);
      return compareTypes(input, expected);
    }
    else if (input instanceof GenericType && (input.impl === impl || (impl && impl.isPrototypeOf(input.impl)))) {
      return 0;
    }
    else {
      return -1;
    }
  }

  unwrap <P> (...typeInstances: Type<P>[]) {
    const {context, impl} = this;
    if (typeof impl !== 'function') {
      return this;
    }
    const annotation = context.getAnnotation(impl);
    if (annotation != null) {
      return (annotation.unwrap(...typeInstances): any);
    }
    else {
      return this;
    }
  }

  inferTypeParameters <P> (input: any): Type<P>[] {
    return [];
  }
}
@@ -30,25 +30,25 @@
 ructor from 
-'
+%22
 ./TypeConstr
@@ -52,17 +52,17 @@
 structor
-'
+%22
 ;%0A%0Aimpor
@@ -82,16 +82,16 @@
 rom 
-'
+%22
 ./Type
-'
+%22
 ;%0Aim
@@ -113,17 +113,17 @@
 es from 
-'
+%22
 ../compa
@@ -129,17 +129,17 @@
 areTypes
-'
+%22
 ;%0A%0Aimpor
@@ -208,16 +208,17 @@
 ation, %7B
+ 
 ErrorTup
@@ -239,16 +239,17 @@
 Path
+ 
 %7D from 
-'
+%22
 ../V
@@ -257,17 +257,17 @@
 lidation
-'
+%22
 ;%0A%0Aexpor
@@ -320,17 +320,16 @@
 uctor %7B%0A
-%0A
   typeNa
@@ -341,17 +341,17 @@
 tring = 
-'
+%22
 GenericT
@@ -353,17 +353,17 @@
 ericType
-'
+%22
 ;%0A%0A  *er
@@ -366,18 +366,22 @@
  *errors
- 
 (
+%0A    
 validati
@@ -400,16 +400,20 @@
 on%3Cany%3E,
+%0A   
  path: I
@@ -422,24 +422,28 @@
 ntifierPath,
+%0A   
  input: any)
@@ -441,16 +441,19 @@
 put: any
+%0A  
 ): Gener
@@ -494,16 +494,17 @@
  const %7B
+ 
 name, im
@@ -509,17 +509,9 @@
 impl
-, context
+ 
 %7D = 
@@ -516,17 +516,16 @@
 = this;%0A
-%0A
     if (
@@ -587,17 +587,17 @@
 Message(
-'
+%22
 ERR_EXPE
@@ -609,17 +609,17 @@
 STANCEOF
-'
+%22
 , name),
@@ -636,171 +636,8 @@
   %7D%0A
-    else %7B%0A      const annotation = context.getAnnotation(impl);%0A      if (annotation) %7B%0A        yield * annotation.errors(validation, path, input);%0A      %7D%0A    %7D%0A
   %7D%0A
@@ -646,21 +646,19 @@
  accepts
- 
 %3CP%3E
- 
 (input: 
@@ -709,37 +709,30 @@
 %0A    const %7B
-context,
  impl
+ 
 %7D = this;%0A  
@@ -737,221 +737,37 @@
     
-if (!(input instanceof impl)) %7B%0A      return false;%0A    %7D%0A    const annotation = context.getAnnotation(impl);%0A    if (annotation) %7B%0A      return annotation.accepts(input);%0A    %7D%0A    else %7B%0A      return true;%0A    %7D
+return input instanceof impl;
 %0A  %7D
@@ -781,21 +781,19 @@
 pareWith
- 
 %3CP%3E
- 
 (input: 
@@ -849,32 +849,33 @@
  1 %7B%0A    const %7B
+ 
 context, impl%7D =
@@ -863,32 +863,33 @@
  %7B context, impl
+ 
 %7D = this;%0A    co
@@ -1061,28 +1061,24 @@
 cted);%0A    %7D
-%0A   
  else if (in
@@ -1075,16 +1075,23 @@
 lse if (
+%0A      
 input in
@@ -1113,16 +1113,22 @@
 cType &&
+%0A     
  (input.
@@ -1185,16 +1185,21 @@
 .impl)))
+%0A    
 ) %7B%0A    
@@ -1211,28 +1211,24 @@
 urn 0;%0A    %7D
-%0A   
  else %7B%0A    
@@ -1259,21 +1259,19 @@
   unwrap
- 
 %3CP%3E
- 
 (...type
@@ -1305,16 +1305,17 @@
  const %7B
+ 
 context,
@@ -1319,16 +1319,17 @@
 xt, impl
+ 
 %7D = this
@@ -1358,17 +1358,17 @@
 !== 
-'
+%22
 function
 ') %7B
@@ -1367,9 +1367,9 @@
 tion
-'
+%22
 ) %7B%0A
@@ -1537,20 +1537,16 @@
 );%0A    %7D
-%0A   
  else %7B%0A
@@ -1600,13 +1600,11 @@
 ters
- 
 %3CP%3E
- 
 (inp
@@ -1645,8 +1645,9 @@
 %5D;%0A  %7D%0A%7D
+%0A

Use nominitive types for GenericTypeAnnotations