// Copyright 2022 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

import objectPath from 'object-path';
import {Decoder, Encoder} from 'pigweedjs/pw_hdlc';
import {Client, Channel, ServiceClient, UnaryMethodStub, MethodStub} from 'pigweedjs/pw_rpc';
import {WebSerialTransport} from '../transport/web_serial_transport';
import {ProtoCollection} from 'pigweedjs/pw_protobuf_compiler';

function titleCase(string) {
  return string.charAt(0).toUpperCase() + string.slice(1);
}

export class Device {
  private protoCollection: ProtoCollection;
  private transport: WebSerialTransport;
  private decoder: Decoder;
  private encoder: Encoder;
  private rpcAddress: number;
  client: Client;
  rpcs: any

  constructor(
    protoCollection: ProtoCollection,
    transport: WebSerialTransport = new WebSerialTransport(),
    rpcAddress: number = 82) {
    this.transport = transport;
    this.rpcAddress = rpcAddress;
    this.protoCollection = protoCollection;
    this.decoder = new Decoder();
    this.encoder = new Encoder();
    const channels = [
      new Channel(1, (bytes) => {
        const hdlcBytes = this.encoder.uiFrame(this.rpcAddress, bytes);
        this.transport.sendChunk(hdlcBytes);
      })];
    this.client =
      Client.fromProtoSet(channels, this.protoCollection);

    this.setupRpcs();
  }

  async connect() {
    await this.transport.connect();
    this.transport.chunks.subscribe((item) => {
      const decoded = this.decoder.process(item);
      for (const frame of decoded) {
        if (frame.address === this.rpcAddress) {
          this.client.processPacket(frame.data);
        }
      }
    });
  }

  private setupRpcs() {
    let rpcMap = {};
    let channel = this.client.channel();
    let servicesKeys = Array.from(channel.services.keys());
    servicesKeys.forEach((serviceKey) => {
      objectPath.set(rpcMap, serviceKey,
        this.mapServiceMethods(channel.services.get(serviceKey))
      );
    });
    this.rpcs = rpcMap;
  }

  private mapServiceMethods(service: ServiceClient) {
    let methodMap = {};
    let methodKeys = Array.from(service.methodsByName.keys());
    methodKeys
      .filter((method: any) => service.methodsByName.get(method) instanceof UnaryMethodStub)
      .forEach(key => {
        let fn = this.createMethodWrapper(
          service.methodsByName.get(key),
          key,
          `${service.name}.${key}`
        );
        methodMap[key] = fn;
      });
    return methodMap;
  }

  private createMethodWrapper(realMethod: MethodStub, methodName: string, fullMethodPath: string) {
    const requestType = realMethod.method.descriptor.getInputType().replace(/^\./, '');
    const requestProtoDescriptor = this.protoCollection.getDescriptorProto(requestType);
    const requestFields = requestProtoDescriptor.getFieldList();
    const functionArguments = requestFields
      .map(field => field.getName())
      .concat(
        'return this(arguments);'
      );

    // We create a new JS function dynamically here that takes
    // proto message fields as arguments and calls the actual RPC method.
    let fn = new Function(...functionArguments).bind((args) => {
      const request = new realMethod.method.requestType();
      requestFields.forEach((field, index) => {
        console.log("setting", `set${titleCase(field.getName())}`, args[index]);
        request[`set${titleCase(field.getName())}`](args[index]);
      })
      if (realMethod instanceof UnaryMethodStub) {
        return realMethod.call(request);
      }
    });
    return fn;
  }
}
