import steem from 'steem';
import { version as steemBotVersion } from '../package.json';

/**
 * This function is extracted from condenser source code and does the same tasks with some slight-
 * adjustments to meet our needs. Refer to the main one in case of future problems:
 * https://github.com/steemit/condenser/blob/edac65e307bffc23f763ed91cebcb4499223b356/app/redux/TransactionSaga.js#L340
 *
 */
function createCommentPermlink(parentAuthor, parentPermlink, postingKey, activeKey) {
  let permlink;

  // comments: re-parentauthor-parentpermlink-time
  const timeStr = new Date().toISOString().replace(/[^a-zA-Z0-9]+/g, '');
  const newParentPermlink = parentPermlink.replace(/(-\d{8}t\d{9}z)/g, '');
  permlink = `re-${parentAuthor}-${newParentPermlink}-${timeStr}`;

  if (permlink.length > 255) {
    // STEEMIT_MAX_PERMLINK_LENGTH
    permlink = permlink.substring(permlink.length - 255, permlink.length);
  }
  // only letters numbers and dashes shall survive
  permlink = permlink.toLowerCase().replace(/[^a-z0-9-]+/g, '');
  return permlink;
}

function getContent(author, permlink) {
  return steem.api.getContentAsync(author, permlink);
}

function convert2VotingWeight(votingPercentage) {
  return Math.min(votingPercentage.toFixed(2) * 100, 10000);
}

export default class Responder {
  constructor(targetUsername, targetPermlink, responderUsername, postingKey, activeKey) {
    this.targetUsername = targetUsername;
    this.targetPermlink = targetPermlink;
    this.responderUsername = responderUsername;
    this.postingKey = postingKey;
    this.activeKey = activeKey;
  }

  _throwErrorIfNoKey() {
    if (!(this.postingKey || this.activeKey)) {
      throw(
        new Error('You need to introduce a postingKey or activeKey to SteemBot\'s constructor')
      );
    }
  }

  _throwErrorIfNoActiveKey() {
    if (!(this.activeKey)) {
      throw(
        new Error('You need to introduce an activeKey to SteemBot\'s constructor')
      );
    }
  }

  _throwErrorIfNoPermlink() {
    if (!this.targetPermlink) {
      throw(
        new Error(
          'You cannot send a comment to a responder comming from a deposit. There is no address to send a comment to!'
        )
      );
    }
  }

  sendSteem(amount, memo = '') {
    this._throwErrorIfNoActiveKey();

    const from = this.responderUsername;
    const to = this.targetUsername;
    amount = `${parseFloat(amount)} STEEM`;

    return steem.broadcast.transferAsync(
      this.activeKey,
      from,
      to,
      amount,
      memo
    );
  }

  sendSbd(amount, memo) {
    this._throwErrorIfNoActiveKey();

    const from = this.responderUsername;
    const to = this.targetUsername;
    amount = `${parseFloat(amount)} SBD`;

    return steem.broadcast.transferAsync(
      this.activeKey,
      from,
      to,
      amount,
      memo
    );
  }

  comment(message) {
    // early exits
    this._throwErrorIfNoPermlink();
    this._throwErrorIfNoKey();

    const permlink = createCommentPermlink(this.targetUsername, this.targetPermlink);
    const wif = this.postingKey || this.activeKey;
    const jsonMetadata = JSON.stringify({
      app: `steembot/${steemBotVersion}`,
    });

    steem.broadcast.commentAsync(
      wif,
      this.targetUsername,
      this.targetPermlink,
      this.responderUsername,
      permlink,
      '',
      message,
      jsonMetadata,
    ).catch(err => {
      throw(new Error(`Error in sending comment to ${this.targetUsername}/${this.targetPermlink}\n${err.message}`));
    });
  }

  upvote(votingPercentage = 100.0) {
    this._throwErrorIfNoKey();

    if (typeof(votingPercentage) === 'string') {
      votingPercentage = parseFloat(votingPercentage);
    }

    if (votingPercentage < 0) {
      throw(new Error(`Don't use negative numbers on upvote() method. Use downvote() instead.`));
    }

    const votingWeight = convert2VotingWeight(votingPercentage);
    const wif = this.postingKey || this.activeKey;

    steem.broadcast.voteAsync(
      wif,
      this.responderUsername,
      this.targetUsername,
      this.targetPermlink,
      votingWeight
    ).catch((err) => {
      throw(new Error(`Error in voting`));
    });
  }

  downvote(votingPercentage = 100.0) {
    this._throwErrorIfNoKey();

    if (typeof(votingPercentage) === 'string') {
      votingPercentage = parseFloat(votingPercentage);
    }

    if (votingPercentage < 0) {
      throw(
        new Error(
          `Don't use negative numbers on downvote() method. The vote will be negative from this API anyway.`
        )
      );
    }

    const votingWeight = convert2VotingWeight(votingPercentage) * -1;
    const wif = this.postingKey || this.activeKey;

    steem.broadcast.voteAsync(
      wif,
      this.responderUsername,
      this.targetUsername,
      this.targetPermlink,
      votingWeight,
    ).catch((err) => {
      throw(new Error(`Error in voting from Steem API ${err.message}`));
    });
  }
}

@@ -3171,24 +3171,31 @@
    %7D);%0A%0A    
+return 
 steem.broadc
@@ -3208,24 +3208,24 @@
 mmentAsync(%0A
-
       wif,%0A 
@@ -3376,147 +3376,8 @@
     
-).catch(err =%3E %7B%0A      throw(new Error(%60Error in sending comment to $%7Bthis.targetUsername%7D/$%7Bthis.targetPermlink%7D%5Cn$%7Berr.message%7D%60));%0A    %7D
 );%0A 
@@ -3810,32 +3810,39 @@
 activeKey;%0A%0A    
+return 
 steem.broadcast.
@@ -3974,75 +3974,8 @@
     
-).catch((err) =%3E %7B%0A      throw(new Error(%60Error in voting%60));%0A    %7D
 );%0A 
@@ -4485,16 +4485,23 @@
 y;%0A%0A    
+return 
 steem.br
@@ -4638,109 +4638,12 @@
 ht,%0A
+
     
-).catch((err) =%3E %7B%0A      throw(new Error(%60Error in voting from Steem API $%7Berr.message%7D%60));%0A    %7D
 );%0A 

make sure all methods return promises