declare namespace gapi {
  declare function load(client: string, callback: () => Promise<any>): void;
  
  interface GoogleConsentRequest {
    apiKey: string;
    clientId: string;
    discoveryDocs: string[];
    scope: string;
  }

  declare namespace client {
    declare function init(initData: GoogleConsentRequest): void;

    declare namespace drive {
      declare namespace files {
        interface Spreadsheet {
          id: string;
          name: string;
        }

        interface SpreadsheetListResponse {
          result: {
            files: Spreadsheet[];
          }
        }

        declare function list(query: { q: string }): Promise<SpreadsheetListResponse>;
      }
    }

    declare namespace sheets {
      declare namespace spreadsheets {
        interface SpreadsheetRangesResponseSheets {
          properties: {
            title: string;
          }
        }

        interface SpreadsheetRangesResponse {
          result: {
            sheets: SpreadsheetRangesResponseSheets[];
          }
        }

        declare function get(query: { spreadsheetId: string; }): Promise<SpreadsheetRangesResponse>;

        declare namespace values {
          interface SpreadsheetDataResponse {
            result: {
              values: any[];
            }
          }

          declare function get(
            spreadsheetData: { spreadsheetId: string; range: string; }
          ): Promise<SpreadsheetDataResponse>;
        }
      }
    }
  }

  interface AuthInstance {
    signIn: () => Promise<{
      isSignedIn: () => boolean;
    }>;

    isSignedIn: {
      listen(callback: (isSignedIn: boolean) => void): AuthSignInListener;
      get(): boolean;
    }

    currentUser: {
      get: () => GoogleUser;
    }
  }

  interface AuthSignInListener {
    remove: () => void;
  }

  interface GoogleUser {
    hasGrantedScopes: (scopes: string) => boolean;
    grant: (data: GoogleConsentRequest) => Promise<any>;
    isSignedIn: () => boolean;
  }

  declare namespace auth2 {
    declare function getAuthInstance(): AuthInstance;
  }

  declare namespace sharetoclassroom {
    declare function go(id: string): void;
  }
}