var img$2 = "data:image/png;base64,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AADiBBYAQJjAAgAIE1gAAGECCwAgTGABAIQJLACAMIEFABAmsAAAwgQWAECYwAIACBNYAABhAgsAIExgAQCECSwAgDCBBQAQJrAAAMIEFgBAmMACAAgTWAAAYQILACBMYAEAhAksAIAwgQUAECawAADCBBYAQJjAAgAIE1gAAGECCwAgTGABAIQJLIAWG4/HdQK6RGABtNjjx4/rBHSJwIKgp0+f1gky/vTbP9YJ6BKBBUEHn39VJ7i7J0+e1AnoGoEFYffv368TTO/58+fl8e4f6groGoEFYed/Pivrx4O6gttrTq5+87df1xXQRQILZqSJrC+++KI8e/as7sD/1vy14Ndff33ze+PkCrpv5eRiMtnqlbJ2VHcAAJjK4W4p+9tOsAAA4gQWAECYwAIACBNYAABhAgsAIExgAQCECSwAgDCBBQAQJrAAAMIEFgBAmMACAAgTWAAAYQILACBMYAEAhAksAIAwgQUAECawAADCBBYAQJjAAgAIE1gAAGECCwAgTGABAIQJLACAMIEFABAmsAAAwgQWAECYwAIACBNYAABhAgsAIExgAQCECSwAgDCBBQAQJrAAAMIEFgBAmMACAAgTWAAAYQILACBMYAEAhAksAIAwgQUAECawAADCBBYAQJjAAgAIE1gAAGECCwAgTGABAIQJLACAMIEFABAmsAAAwgQWAECYwAIACBNYAABhAgsAIExgAQCECSwAgDCBBQAQJrAAAMIEFgBAmMACAAgTWAAAYQILACBMYAEAhAksAIAwgQUAECawAADCBBYAQJjAAgAIE1gAAGECCwAgTGABAIQJLACAMIEFABAmsAAAwgQWAECYwAIACBNYAABhKycXk8kvV0v5y8u6AwDAVH71WSnDXin/Bna6qnUpkFCVAAAAAElFTkSuQmCC";

var img$1 = "data:image/svg+xml,%3csvg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='152.06552' height='163.58806' viewBox='0%2c0%2c152.06552%2c163.58806'%3e%3cg transform='translate(-163.96724%2c-98.20597)'%3e%3cg data-paper-data='%7b%26quot%3bisPaintingLayer%26quot%3b:true%7d' fill-rule='nonzero' stroke='black' stroke-width='0.5' stroke-linecap='butt' stroke-linejoin='miter' stroke-miterlimit='10' stroke-dasharray='' stroke-dashoffset='0' style='mix-blend-mode: normal'%3e%3cpath d='M164.21724%2c261.54403v-163.08806h151.56552v163.08806z' fill='%23f7f7f7'/%3e%3cpath d='M189.82568%2c217.21608v-72.53493h102.84804v72.53493z' fill='white'/%3e%3cpath d='M213.6822%2c195.73702v-28.42734h12.18314v28.42734z' fill='%23b1b1b1'/%3e%3cpath d='M253.49118%2c196.09582v-28.42733h12.18314v28.42734z' fill='%23b1b1b1'/%3e%3c/g%3e%3c/g%3e%3c/svg%3e";

var en$1 = {
	"websockExt.entry.name": "Network Extension(v0.2.1)",
	"websockExt.entry.description": "Network communication"
};
var ja$1 = {
	"websockExt.entry.name": "ネットワーク拡張(v0.2.1)",
	"websockExt.entry.description": "ネットワーク通信をします"
};
var translations$1 = {
	en: en$1,
	ja: ja$1,
	"ja-Hira": {
	"websockExt.entry.name": "ネットワークかくちょう(v0.2.1)",
	"websockExt.entry.description": "ネットワークつうしんをします"
}
};

/**
 * This is an extension for Xcratch.
 */

/**
 * Formatter to translate the messages in this extension.
 * This will be replaced which is used in the React component.
 * @param {object} messageData - data for format-message
 * @returns {string} - translated message for the current locale
 */
var formatMessage$1 = function formatMessage(messageData) {
  return messageData.defaultMessage;
};
var entry = {
  get name() {
    return formatMessage$1({
      id: 'websockExt.entry.name',
      default: "Websock 拡張",
      description: 'name of the extension'
    });
  },
  extensionId: 'websockExt',
  extensionURL: 'https://pcratch.j-code.org/xcratch-extensions/websock-ext/dist/websockExt.mjs',
  collaborator: '',
  iconURL: img$2,
  insetIconURL: img$1,
  get description() {
    return formatMessage$1({
      id: 'websockExt.entry.description',
      defaultMessage: "WebSocket でネットワーク通信をします",
      description: 'Description for this extension'
    });
  },
  featured: true,
  disabled: false,
  bluetoothRequired: false,
  internetConnectionRequired: false,
  helpLink: 'https://pcratch.j-code.org/',
  setFormatMessage: function setFormatMessage(formatter) {
    formatMessage$1 = formatter;
  },
  translationMap: translations$1
};

function _typeof$1(obj) {
  "@babel/helpers - typeof";

  return _typeof$1 = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) {
    return typeof obj;
  } : function (obj) {
    return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
  }, _typeof$1(obj);
}

function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
  try {
    var info = gen[key](arg);
    var value = info.value;
  } catch (error) {
    reject(error);
    return;
  }
  if (info.done) {
    resolve(value);
  } else {
    Promise.resolve(value).then(_next, _throw);
  }
}
function _asyncToGenerator(fn) {
  return function () {
    var self = this,
      args = arguments;
    return new Promise(function (resolve, reject) {
      var gen = fn.apply(self, args);
      function _next(value) {
        asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
      }
      function _throw(err) {
        asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
      }
      _next(undefined);
    });
  };
}

function _classCallCheck(instance, Constructor) {
  if (!(instance instanceof Constructor)) {
    throw new TypeError("Cannot call a class as a function");
  }
}

function _toPrimitive(input, hint) {
  if (_typeof$1(input) !== "object" || input === null) return input;
  var prim = input[Symbol.toPrimitive];
  if (prim !== undefined) {
    var res = prim.call(input, hint || "default");
    if (_typeof$1(res) !== "object") return res;
    throw new TypeError("@@toPrimitive must return a primitive value.");
  }
  return (hint === "string" ? String : Number)(input);
}

function _toPropertyKey(arg) {
  var key = _toPrimitive(arg, "string");
  return _typeof$1(key) === "symbol" ? key : String(key);
}

function _defineProperties(target, props) {
  for (var i = 0; i < props.length; i++) {
    var descriptor = props[i];
    descriptor.enumerable = descriptor.enumerable || false;
    descriptor.configurable = true;
    if ("value" in descriptor) descriptor.writable = true;
    Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor);
  }
}
function _createClass(Constructor, protoProps, staticProps) {
  if (protoProps) _defineProperties(Constructor.prototype, protoProps);
  if (staticProps) _defineProperties(Constructor, staticProps);
  Object.defineProperty(Constructor, "prototype", {
    writable: false
  });
  return Constructor;
}

var regeneratorRuntime$1 = {exports: {}};

var _typeof = {exports: {}};

(function (module) {
  function _typeof(obj) {
    "@babel/helpers - typeof";

    return (module.exports = _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) {
      return typeof obj;
    } : function (obj) {
      return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
    }, module.exports.__esModule = true, module.exports["default"] = module.exports), _typeof(obj);
  }
  module.exports = _typeof, module.exports.__esModule = true, module.exports["default"] = module.exports;
})(_typeof);

(function (module) {
  var _typeof$1 = _typeof.exports["default"];
  function _regeneratorRuntime() {

    /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */
    module.exports = _regeneratorRuntime = function _regeneratorRuntime() {
      return exports;
    }, module.exports.__esModule = true, module.exports["default"] = module.exports;
    var exports = {},
      Op = Object.prototype,
      hasOwn = Op.hasOwnProperty,
      defineProperty = Object.defineProperty || function (obj, key, desc) {
        obj[key] = desc.value;
      },
      $Symbol = "function" == typeof Symbol ? Symbol : {},
      iteratorSymbol = $Symbol.iterator || "@@iterator",
      asyncIteratorSymbol = $Symbol.asyncIterator || "@@asyncIterator",
      toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag";
    function define(obj, key, value) {
      return Object.defineProperty(obj, key, {
        value: value,
        enumerable: !0,
        configurable: !0,
        writable: !0
      }), obj[key];
    }
    try {
      define({}, "");
    } catch (err) {
      define = function define(obj, key, value) {
        return obj[key] = value;
      };
    }
    function wrap(innerFn, outerFn, self, tryLocsList) {
      var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator,
        generator = Object.create(protoGenerator.prototype),
        context = new Context(tryLocsList || []);
      return defineProperty(generator, "_invoke", {
        value: makeInvokeMethod(innerFn, self, context)
      }), generator;
    }
    function tryCatch(fn, obj, arg) {
      try {
        return {
          type: "normal",
          arg: fn.call(obj, arg)
        };
      } catch (err) {
        return {
          type: "throw",
          arg: err
        };
      }
    }
    exports.wrap = wrap;
    var ContinueSentinel = {};
    function Generator() {}
    function GeneratorFunction() {}
    function GeneratorFunctionPrototype() {}
    var IteratorPrototype = {};
    define(IteratorPrototype, iteratorSymbol, function () {
      return this;
    });
    var getProto = Object.getPrototypeOf,
      NativeIteratorPrototype = getProto && getProto(getProto(values([])));
    NativeIteratorPrototype && NativeIteratorPrototype !== Op && hasOwn.call(NativeIteratorPrototype, iteratorSymbol) && (IteratorPrototype = NativeIteratorPrototype);
    var Gp = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(IteratorPrototype);
    function defineIteratorMethods(prototype) {
      ["next", "throw", "return"].forEach(function (method) {
        define(prototype, method, function (arg) {
          return this._invoke(method, arg);
        });
      });
    }
    function AsyncIterator(generator, PromiseImpl) {
      function invoke(method, arg, resolve, reject) {
        var record = tryCatch(generator[method], generator, arg);
        if ("throw" !== record.type) {
          var result = record.arg,
            value = result.value;
          return value && "object" == _typeof$1(value) && hasOwn.call(value, "__await") ? PromiseImpl.resolve(value.__await).then(function (value) {
            invoke("next", value, resolve, reject);
          }, function (err) {
            invoke("throw", err, resolve, reject);
          }) : PromiseImpl.resolve(value).then(function (unwrapped) {
            result.value = unwrapped, resolve(result);
          }, function (error) {
            return invoke("throw", error, resolve, reject);
          });
        }
        reject(record.arg);
      }
      var previousPromise;
      defineProperty(this, "_invoke", {
        value: function value(method, arg) {
          function callInvokeWithMethodAndArg() {
            return new PromiseImpl(function (resolve, reject) {
              invoke(method, arg, resolve, reject);
            });
          }
          return previousPromise = previousPromise ? previousPromise.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg();
        }
      });
    }
    function makeInvokeMethod(innerFn, self, context) {
      var state = "suspendedStart";
      return function (method, arg) {
        if ("executing" === state) throw new Error("Generator is already running");
        if ("completed" === state) {
          if ("throw" === method) throw arg;
          return doneResult();
        }
        for (context.method = method, context.arg = arg;;) {
          var delegate = context.delegate;
          if (delegate) {
            var delegateResult = maybeInvokeDelegate(delegate, context);
            if (delegateResult) {
              if (delegateResult === ContinueSentinel) continue;
              return delegateResult;
            }
          }
          if ("next" === context.method) context.sent = context._sent = context.arg;else if ("throw" === context.method) {
            if ("suspendedStart" === state) throw state = "completed", context.arg;
            context.dispatchException(context.arg);
          } else "return" === context.method && context.abrupt("return", context.arg);
          state = "executing";
          var record = tryCatch(innerFn, self, context);
          if ("normal" === record.type) {
            if (state = context.done ? "completed" : "suspendedYield", record.arg === ContinueSentinel) continue;
            return {
              value: record.arg,
              done: context.done
            };
          }
          "throw" === record.type && (state = "completed", context.method = "throw", context.arg = record.arg);
        }
      };
    }
    function maybeInvokeDelegate(delegate, context) {
      var methodName = context.method,
        method = delegate.iterator[methodName];
      if (undefined === method) return context.delegate = null, "throw" === methodName && delegate.iterator["return"] && (context.method = "return", context.arg = undefined, maybeInvokeDelegate(delegate, context), "throw" === context.method) || "return" !== methodName && (context.method = "throw", context.arg = new TypeError("The iterator does not provide a '" + methodName + "' method")), ContinueSentinel;
      var record = tryCatch(method, delegate.iterator, context.arg);
      if ("throw" === record.type) return context.method = "throw", context.arg = record.arg, context.delegate = null, ContinueSentinel;
      var info = record.arg;
      return info ? info.done ? (context[delegate.resultName] = info.value, context.next = delegate.nextLoc, "return" !== context.method && (context.method = "next", context.arg = undefined), context.delegate = null, ContinueSentinel) : info : (context.method = "throw", context.arg = new TypeError("iterator result is not an object"), context.delegate = null, ContinueSentinel);
    }
    function pushTryEntry(locs) {
      var entry = {
        tryLoc: locs[0]
      };
      1 in locs && (entry.catchLoc = locs[1]), 2 in locs && (entry.finallyLoc = locs[2], entry.afterLoc = locs[3]), this.tryEntries.push(entry);
    }
    function resetTryEntry(entry) {
      var record = entry.completion || {};
      record.type = "normal", delete record.arg, entry.completion = record;
    }
    function Context(tryLocsList) {
      this.tryEntries = [{
        tryLoc: "root"
      }], tryLocsList.forEach(pushTryEntry, this), this.reset(!0);
    }
    function values(iterable) {
      if (iterable) {
        var iteratorMethod = iterable[iteratorSymbol];
        if (iteratorMethod) return iteratorMethod.call(iterable);
        if ("function" == typeof iterable.next) return iterable;
        if (!isNaN(iterable.length)) {
          var i = -1,
            next = function next() {
              for (; ++i < iterable.length;) {
                if (hasOwn.call(iterable, i)) return next.value = iterable[i], next.done = !1, next;
              }
              return next.value = undefined, next.done = !0, next;
            };
          return next.next = next;
        }
      }
      return {
        next: doneResult
      };
    }
    function doneResult() {
      return {
        value: undefined,
        done: !0
      };
    }
    return GeneratorFunction.prototype = GeneratorFunctionPrototype, defineProperty(Gp, "constructor", {
      value: GeneratorFunctionPrototype,
      configurable: !0
    }), defineProperty(GeneratorFunctionPrototype, "constructor", {
      value: GeneratorFunction,
      configurable: !0
    }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, toStringTagSymbol, "GeneratorFunction"), exports.isGeneratorFunction = function (genFun) {
      var ctor = "function" == typeof genFun && genFun.constructor;
      return !!ctor && (ctor === GeneratorFunction || "GeneratorFunction" === (ctor.displayName || ctor.name));
    }, exports.mark = function (genFun) {
      return Object.setPrototypeOf ? Object.setPrototypeOf(genFun, GeneratorFunctionPrototype) : (genFun.__proto__ = GeneratorFunctionPrototype, define(genFun, toStringTagSymbol, "GeneratorFunction")), genFun.prototype = Object.create(Gp), genFun;
    }, exports.awrap = function (arg) {
      return {
        __await: arg
      };
    }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, asyncIteratorSymbol, function () {
      return this;
    }), exports.AsyncIterator = AsyncIterator, exports.async = function (innerFn, outerFn, self, tryLocsList, PromiseImpl) {
      void 0 === PromiseImpl && (PromiseImpl = Promise);
      var iter = new AsyncIterator(wrap(innerFn, outerFn, self, tryLocsList), PromiseImpl);
      return exports.isGeneratorFunction(outerFn) ? iter : iter.next().then(function (result) {
        return result.done ? result.value : iter.next();
      });
    }, defineIteratorMethods(Gp), define(Gp, toStringTagSymbol, "Generator"), define(Gp, iteratorSymbol, function () {
      return this;
    }), define(Gp, "toString", function () {
      return "[object Generator]";
    }), exports.keys = function (val) {
      var object = Object(val),
        keys = [];
      for (var key in object) {
        keys.push(key);
      }
      return keys.reverse(), function next() {
        for (; keys.length;) {
          var key = keys.pop();
          if (key in object) return next.value = key, next.done = !1, next;
        }
        return next.done = !0, next;
      };
    }, exports.values = values, Context.prototype = {
      constructor: Context,
      reset: function reset(skipTempReset) {
        if (this.prev = 0, this.next = 0, this.sent = this._sent = undefined, this.done = !1, this.delegate = null, this.method = "next", this.arg = undefined, this.tryEntries.forEach(resetTryEntry), !skipTempReset) for (var name in this) {
          "t" === name.charAt(0) && hasOwn.call(this, name) && !isNaN(+name.slice(1)) && (this[name] = undefined);
        }
      },
      stop: function stop() {
        this.done = !0;
        var rootRecord = this.tryEntries[0].completion;
        if ("throw" === rootRecord.type) throw rootRecord.arg;
        return this.rval;
      },
      dispatchException: function dispatchException(exception) {
        if (this.done) throw exception;
        var context = this;
        function handle(loc, caught) {
          return record.type = "throw", record.arg = exception, context.next = loc, caught && (context.method = "next", context.arg = undefined), !!caught;
        }
        for (var i = this.tryEntries.length - 1; i >= 0; --i) {
          var entry = this.tryEntries[i],
            record = entry.completion;
          if ("root" === entry.tryLoc) return handle("end");
          if (entry.tryLoc <= this.prev) {
            var hasCatch = hasOwn.call(entry, "catchLoc"),
              hasFinally = hasOwn.call(entry, "finallyLoc");
            if (hasCatch && hasFinally) {
              if (this.prev < entry.catchLoc) return handle(entry.catchLoc, !0);
              if (this.prev < entry.finallyLoc) return handle(entry.finallyLoc);
            } else if (hasCatch) {
              if (this.prev < entry.catchLoc) return handle(entry.catchLoc, !0);
            } else {
              if (!hasFinally) throw new Error("try statement without catch or finally");
              if (this.prev < entry.finallyLoc) return handle(entry.finallyLoc);
            }
          }
        }
      },
      abrupt: function abrupt(type, arg) {
        for (var i = this.tryEntries.length - 1; i >= 0; --i) {
          var entry = this.tryEntries[i];
          if (entry.tryLoc <= this.prev && hasOwn.call(entry, "finallyLoc") && this.prev < entry.finallyLoc) {
            var finallyEntry = entry;
            break;
          }
        }
        finallyEntry && ("break" === type || "continue" === type) && finallyEntry.tryLoc <= arg && arg <= finallyEntry.finallyLoc && (finallyEntry = null);
        var record = finallyEntry ? finallyEntry.completion : {};
        return record.type = type, record.arg = arg, finallyEntry ? (this.method = "next", this.next = finallyEntry.finallyLoc, ContinueSentinel) : this.complete(record);
      },
      complete: function complete(record, afterLoc) {
        if ("throw" === record.type) throw record.arg;
        return "break" === record.type || "continue" === record.type ? this.next = record.arg : "return" === record.type ? (this.rval = this.arg = record.arg, this.method = "return", this.next = "end") : "normal" === record.type && afterLoc && (this.next = afterLoc), ContinueSentinel;
      },
      finish: function finish(finallyLoc) {
        for (var i = this.tryEntries.length - 1; i >= 0; --i) {
          var entry = this.tryEntries[i];
          if (entry.finallyLoc === finallyLoc) return this.complete(entry.completion, entry.afterLoc), resetTryEntry(entry), ContinueSentinel;
        }
      },
      "catch": function _catch(tryLoc) {
        for (var i = this.tryEntries.length - 1; i >= 0; --i) {
          var entry = this.tryEntries[i];
          if (entry.tryLoc === tryLoc) {
            var record = entry.completion;
            if ("throw" === record.type) {
              var thrown = record.arg;
              resetTryEntry(entry);
            }
            return thrown;
          }
        }
        throw new Error("illegal catch attempt");
      },
      delegateYield: function delegateYield(iterable, resultName, nextLoc) {
        return this.delegate = {
          iterator: values(iterable),
          resultName: resultName,
          nextLoc: nextLoc
        }, "next" === this.method && (this.arg = undefined), ContinueSentinel;
      }
    }, exports;
  }
  module.exports = _regeneratorRuntime, module.exports.__esModule = true, module.exports["default"] = module.exports;
})(regeneratorRuntime$1);

// TODO(Babel 8): Remove this file.

var runtime = regeneratorRuntime$1.exports();
var regenerator = runtime;

// Copied from https://github.com/facebook/regenerator/blob/main/packages/runtime/runtime.js#L736=
try {
  regeneratorRuntime = runtime;
} catch (accidentalStrictMode) {
  if ((typeof globalThis === "undefined" ? "undefined" : _typeof$1(globalThis)) === "object") {
    globalThis.regeneratorRuntime = runtime;
  } else {
    Function("r", "regeneratorRuntime = r")(runtime);
  }
}

/**
 * Types of block
 * @enum {string}
 */
var BlockType = {
  /**
   * Boolean reporter with hexagonal shape
   */
  BOOLEAN: 'Boolean',
  /**
   * A button (not an actual block) for some special action, like making a variable
   */
  BUTTON: 'button',
  /**
   * Command block
   */
  COMMAND: 'command',
  /**
   * Specialized command block which may or may not run a child branch
   * The thread continues with the next block whether or not a child branch ran.
   */
  CONDITIONAL: 'conditional',
  /**
   * Specialized hat block with no implementation function
   * This stack only runs if the corresponding event is emitted by other code.
   */
  EVENT: 'event',
  /**
   * Hat block which conditionally starts a block stack
   */
  HAT: 'hat',
  /**
   * Specialized command block which may or may not run a child branch
   * If a child branch runs, the thread evaluates the loop block again.
   */
  LOOP: 'loop',
  /**
   * General reporter with numeric or string value
   */
  REPORTER: 'reporter'
};
var blockType = BlockType;

/**
 * Block argument types
 * @enum {string}
 */
var ArgumentType = {
  /**
   * Numeric value with angle picker
   */
  ANGLE: 'angle',
  /**
   * Boolean value with hexagonal placeholder
   */
  BOOLEAN: 'Boolean',
  /**
   * Numeric value with color picker
   */
  COLOR: 'color',
  /**
   * Numeric value with text field
   */
  NUMBER: 'number',
  /**
   * String value with text field
   */
  STRING: 'string',
  /**
   * String value with matrix field
   */
  MATRIX: 'matrix',
  /**
   * MIDI note number with note picker (piano) field
   */
  NOTE: 'note',
  /**
   * Inline image on block (as part of the label)
   */
  IMAGE: 'image'
};
var argumentType = ArgumentType;

var Color$1 = /*#__PURE__*/function () {
  function Color() {
    _classCallCheck(this, Color);
  }
  _createClass(Color, null, [{
    key: "RGB_BLACK",
    get:
    /**
     * @typedef {object} RGBObject - An object representing a color in RGB format.
     * @property {number} r - the red component, in the range [0, 255].
     * @property {number} g - the green component, in the range [0, 255].
     * @property {number} b - the blue component, in the range [0, 255].
     */

    /**
     * @typedef {object} HSVObject - An object representing a color in HSV format.
     * @property {number} h - hue, in the range [0-359).
     * @property {number} s - saturation, in the range [0,1].
     * @property {number} v - value, in the range [0,1].
     */

    /** @type {RGBObject} */
    function get() {
      return {
        r: 0,
        g: 0,
        b: 0
      };
    }

    /** @type {RGBObject} */
  }, {
    key: "RGB_WHITE",
    get: function get() {
      return {
        r: 255,
        g: 255,
        b: 255
      };
    }

    /**
     * Convert a Scratch decimal color to a hex string, #RRGGBB.
     * @param {number} decimal RGB color as a decimal.
     * @return {string} RGB color as #RRGGBB hex string.
     */
  }, {
    key: "decimalToHex",
    value: function decimalToHex(decimal) {
      if (decimal < 0) {
        decimal += 0xFFFFFF + 1;
      }
      var hex = Number(decimal).toString(16);
      hex = "#".concat('000000'.substr(0, 6 - hex.length)).concat(hex);
      return hex;
    }

    /**
     * Convert a Scratch decimal color to an RGB color object.
     * @param {number} decimal RGB color as decimal.
     * @return {RGBObject} rgb - {r: red [0,255], g: green [0,255], b: blue [0,255]}.
     */
  }, {
    key: "decimalToRgb",
    value: function decimalToRgb(decimal) {
      var a = decimal >> 24 & 0xFF;
      var r = decimal >> 16 & 0xFF;
      var g = decimal >> 8 & 0xFF;
      var b = decimal & 0xFF;
      return {
        r: r,
        g: g,
        b: b,
        a: a > 0 ? a : 255
      };
    }

    /**
     * Convert a hex color (e.g., F00, #03F, #0033FF) to an RGB color object.
     * CC-BY-SA Tim Down:
     * https://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb
     * @param {!string} hex Hex representation of the color.
     * @return {RGBObject} null on failure, or rgb: {r: red [0,255], g: green [0,255], b: blue [0,255]}.
     */
  }, {
    key: "hexToRgb",
    value: function hexToRgb(hex) {
      var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
      hex = hex.replace(shorthandRegex, function (m, r, g, b) {
        return r + r + g + g + b + b;
      });
      var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
      return result ? {
        r: parseInt(result[1], 16),
        g: parseInt(result[2], 16),
        b: parseInt(result[3], 16)
      } : null;
    }

    /**
     * Convert an RGB color object to a hex color.
     * @param {RGBObject} rgb - {r: red [0,255], g: green [0,255], b: blue [0,255]}.
     * @return {!string} Hex representation of the color.
     */
  }, {
    key: "rgbToHex",
    value: function rgbToHex(rgb) {
      return Color.decimalToHex(Color.rgbToDecimal(rgb));
    }

    /**
     * Convert an RGB color object to a Scratch decimal color.
     * @param {RGBObject} rgb - {r: red [0,255], g: green [0,255], b: blue [0,255]}.
     * @return {!number} Number representing the color.
     */
  }, {
    key: "rgbToDecimal",
    value: function rgbToDecimal(rgb) {
      return (rgb.r << 16) + (rgb.g << 8) + rgb.b;
    }

    /**
    * Convert a hex color (e.g., F00, #03F, #0033FF) to a decimal color number.
    * @param {!string} hex Hex representation of the color.
    * @return {!number} Number representing the color.
    */
  }, {
    key: "hexToDecimal",
    value: function hexToDecimal(hex) {
      return Color.rgbToDecimal(Color.hexToRgb(hex));
    }

    /**
     * Convert an HSV color to RGB format.
     * @param {HSVObject} hsv - {h: hue [0,360), s: saturation [0,1], v: value [0,1]}
     * @return {RGBObject} rgb - {r: red [0,255], g: green [0,255], b: blue [0,255]}.
     */
  }, {
    key: "hsvToRgb",
    value: function hsvToRgb(hsv) {
      var h = hsv.h % 360;
      if (h < 0) h += 360;
      var s = Math.max(0, Math.min(hsv.s, 1));
      var v = Math.max(0, Math.min(hsv.v, 1));
      var i = Math.floor(h / 60);
      var f = h / 60 - i;
      var p = v * (1 - s);
      var q = v * (1 - s * f);
      var t = v * (1 - s * (1 - f));
      var r;
      var g;
      var b;
      switch (i) {
        default:
        case 0:
          r = v;
          g = t;
          b = p;
          break;
        case 1:
          r = q;
          g = v;
          b = p;
          break;
        case 2:
          r = p;
          g = v;
          b = t;
          break;
        case 3:
          r = p;
          g = q;
          b = v;
          break;
        case 4:
          r = t;
          g = p;
          b = v;
          break;
        case 5:
          r = v;
          g = p;
          b = q;
          break;
      }
      return {
        r: Math.floor(r * 255),
        g: Math.floor(g * 255),
        b: Math.floor(b * 255)
      };
    }

    /**
     * Convert an RGB color to HSV format.
     * @param {RGBObject} rgb - {r: red [0,255], g: green [0,255], b: blue [0,255]}.
     * @return {HSVObject} hsv - {h: hue [0,360), s: saturation [0,1], v: value [0,1]}
     */
  }, {
    key: "rgbToHsv",
    value: function rgbToHsv(rgb) {
      var r = rgb.r / 255;
      var g = rgb.g / 255;
      var b = rgb.b / 255;
      var x = Math.min(Math.min(r, g), b);
      var v = Math.max(Math.max(r, g), b);

      // For grays, hue will be arbitrarily reported as zero. Otherwise, calculate
      var h = 0;
      var s = 0;
      if (x !== v) {
        var f = r === x ? g - b : g === x ? b - r : r - g;
        var i = r === x ? 3 : g === x ? 5 : 1;
        h = (i - f / (v - x)) * 60 % 360;
        s = (v - x) / v;
      }
      return {
        h: h,
        s: s,
        v: v
      };
    }

    /**
     * Linear interpolation between rgb0 and rgb1.
     * @param {RGBObject} rgb0 - the color corresponding to fraction1 <= 0.
     * @param {RGBObject} rgb1 - the color corresponding to fraction1 >= 1.
     * @param {number} fraction1 - the interpolation parameter. If this is 0.5, for example, mix the two colors equally.
     * @return {RGBObject} the interpolated color.
     */
  }, {
    key: "mixRgb",
    value: function mixRgb(rgb0, rgb1, fraction1) {
      if (fraction1 <= 0) return rgb0;
      if (fraction1 >= 1) return rgb1;
      var fraction0 = 1 - fraction1;
      return {
        r: fraction0 * rgb0.r + fraction1 * rgb1.r,
        g: fraction0 * rgb0.g + fraction1 * rgb1.g,
        b: fraction0 * rgb0.b + fraction1 * rgb1.b
      };
    }
  }]);
  return Color;
}();
var color = Color$1;

var Color = color;

/**
 * @fileoverview
 * Utilities for casting and comparing Scratch data-types.
 * Scratch behaves slightly differently from JavaScript in many respects,
 * and these differences should be encapsulated below.
 * For example, in Scratch, add(1, join("hello", world")) -> 1.
 * This is because "hello world" is cast to 0.
 * In JavaScript, 1 + Number("hello" + "world") would give you NaN.
 * Use when coercing a value before computation.
 */
var Cast = /*#__PURE__*/function () {
  function Cast() {
    _classCallCheck(this, Cast);
  }
  _createClass(Cast, null, [{
    key: "toNumber",
    value:
    /**
     * Scratch cast to number.
     * Treats NaN as 0.
     * In Scratch 2.0, this is captured by `interp.numArg.`
     * @param {*} value Value to cast to number.
     * @return {number} The Scratch-casted number value.
     */
    function toNumber(value) {
      // If value is already a number we don't need to coerce it with
      // Number().
      if (typeof value === 'number') {
        // Scratch treats NaN as 0, when needed as a number.
        // E.g., 0 + NaN -> 0.
        if (Number.isNaN(value)) {
          return 0;
        }
        return value;
      }
      var n = Number(value);
      if (Number.isNaN(n)) {
        // Scratch treats NaN as 0, when needed as a number.
        // E.g., 0 + NaN -> 0.
        return 0;
      }
      return n;
    }

    /**
     * Scratch cast to boolean.
     * In Scratch 2.0, this is captured by `interp.boolArg.`
     * Treats some string values differently from JavaScript.
     * @param {*} value Value to cast to boolean.
     * @return {boolean} The Scratch-casted boolean value.
     */
  }, {
    key: "toBoolean",
    value: function toBoolean(value) {
      // Already a boolean?
      if (typeof value === 'boolean') {
        return value;
      }
      if (typeof value === 'string') {
        // These specific strings are treated as false in Scratch.
        if (value === '' || value === '0' || value.toLowerCase() === 'false') {
          return false;
        }
        // All other strings treated as true.
        return true;
      }
      // Coerce other values and numbers.
      return Boolean(value);
    }

    /**
     * Scratch cast to string.
     * @param {*} value Value to cast to string.
     * @return {string} The Scratch-casted string value.
     */
  }, {
    key: "toString",
    value: function toString(value) {
      return String(value);
    }

    /**
     * Cast any Scratch argument to an RGB color array to be used for the renderer.
     * @param {*} value Value to convert to RGB color array.
     * @return {Array.<number>} [r,g,b], values between 0-255.
     */
  }, {
    key: "toRgbColorList",
    value: function toRgbColorList(value) {
      var color = Cast.toRgbColorObject(value);
      return [color.r, color.g, color.b];
    }

    /**
     * Cast any Scratch argument to an RGB color object to be used for the renderer.
     * @param {*} value Value to convert to RGB color object.
     * @return {RGBOject} [r,g,b], values between 0-255.
     */
  }, {
    key: "toRgbColorObject",
    value: function toRgbColorObject(value) {
      var color;
      if (typeof value === 'string' && value.substring(0, 1) === '#') {
        color = Color.hexToRgb(value);

        // If the color wasn't *actually* a hex color, cast to black
        if (!color) color = {
          r: 0,
          g: 0,
          b: 0,
          a: 255
        };
      } else {
        color = Color.decimalToRgb(Cast.toNumber(value));
      }
      return color;
    }

    /**
     * Determine if a Scratch argument is a white space string (or null / empty).
     * @param {*} val value to check.
     * @return {boolean} True if the argument is all white spaces or null / empty.
     */
  }, {
    key: "isWhiteSpace",
    value: function isWhiteSpace(val) {
      return val === null || typeof val === 'string' && val.trim().length === 0;
    }

    /**
     * Compare two values, using Scratch cast, case-insensitive string compare, etc.
     * In Scratch 2.0, this is captured by `interp.compare.`
     * @param {*} v1 First value to compare.
     * @param {*} v2 Second value to compare.
     * @returns {number} Negative number if v1 < v2; 0 if equal; positive otherwise.
     */
  }, {
    key: "compare",
    value: function compare(v1, v2) {
      var n1 = Number(v1);
      var n2 = Number(v2);
      if (n1 === 0 && Cast.isWhiteSpace(v1)) {
        n1 = NaN;
      } else if (n2 === 0 && Cast.isWhiteSpace(v2)) {
        n2 = NaN;
      }
      if (isNaN(n1) || isNaN(n2)) {
        // At least one argument can't be converted to a number.
        // Scratch compares strings as case insensitive.
        var s1 = String(v1).toLowerCase();
        var s2 = String(v2).toLowerCase();
        if (s1 < s2) {
          return -1;
        } else if (s1 > s2) {
          return 1;
        }
        return 0;
      }
      // Handle the special case of Infinity
      if (n1 === Infinity && n2 === Infinity || n1 === -Infinity && n2 === -Infinity) {
        return 0;
      }
      // Compare as numbers.
      return n1 - n2;
    }

    /**
     * Determine if a Scratch argument number represents a round integer.
     * @param {*} val Value to check.
     * @return {boolean} True if number looks like an integer.
     */
  }, {
    key: "isInt",
    value: function isInt(val) {
      // Values that are already numbers.
      if (typeof val === 'number') {
        if (isNaN(val)) {
          // NaN is considered an integer.
          return true;
        }
        // True if it's "round" (e.g., 2.0 and 2).
        return val === parseInt(val, 10);
      } else if (typeof val === 'boolean') {
        // `True` and `false` always represent integer after Scratch cast.
        return true;
      } else if (typeof val === 'string') {
        // If it contains a decimal point, don't consider it an int.
        return val.indexOf('.') < 0;
      }
      return false;
    }
  }, {
    key: "LIST_INVALID",
    get: function get() {
      return 'INVALID';
    }
  }, {
    key: "LIST_ALL",
    get: function get() {
      return 'ALL';
    }

    /**
     * Compute a 1-based index into a list, based on a Scratch argument.
     * Two special cases may be returned:
     * LIST_ALL: if the block is referring to all of the items in the list.
     * LIST_INVALID: if the index was invalid in any way.
     * @param {*} index Scratch arg, including 1-based numbers or special cases.
     * @param {number} length Length of the list.
     * @param {boolean} acceptAll Whether it should accept "all" or not.
     * @return {(number|string)} 1-based index for list, LIST_ALL, or LIST_INVALID.
     */
  }, {
    key: "toListIndex",
    value: function toListIndex(index, length, acceptAll) {
      if (typeof index !== 'number') {
        if (index === 'all') {
          return acceptAll ? Cast.LIST_ALL : Cast.LIST_INVALID;
        }
        if (index === 'last') {
          if (length > 0) {
            return length;
          }
          return Cast.LIST_INVALID;
        } else if (index === 'random' || index === 'any') {
          if (length > 0) {
            return 1 + Math.floor(Math.random() * length);
          }
          return Cast.LIST_INVALID;
        }
      }
      index = Math.floor(Cast.toNumber(index));
      if (index < 1 || index > length) {
        return Cast.LIST_INVALID;
      }
      return index;
    }
  }]);
  return Cast;
}();
var cast = Cast;

var en = {
	send_too_much: "Connection terminated due to too much transmission!",
	"Websock.name": "Network Extension",
	"websock.bind": "Bind to port [PORT]",
	"websock.setname": "Set my address to [TEXT]",
	"websock.close": "Close",
	"websock.send": "Send [TEXT]",
	"websock.sendto": "Send [TEXT] to [SENDTO]",
	"websock.whenrecv": "When received",
	"websock.recv": "Received data",
	"websock.from": "From address",
	"websock.state": "Ready state",
	"websock.numrecv": "Number of received data",
	"websock.nextrecv": "Get the next received data",
	"websock.closed": "Connection closed!",
	webapi_call: "HTTP GET [URL]",
	json_parse: "JSON [JSON] parse [KEY]",
	json_stringify: "JSON [JSON] + [KEY] [VALUE]"
};
var ja = {
	send_too_much: "送信が多すぎなので、接続をクローズしました！",
	"Websock.name": "ネットワーク拡張",
	"websock.bind": "送受信 ポート [PORT]",
	"websock.setname": "自分のアドレスを [TEXT] にする",
	"websock.close": "切断",
	"websock.send": "[TEXT] を送信",
	"websock.sendto": "[TEXT] を [SENDTO] に送信",
	"websock.whenrecv": "受信したとき",
	"websock.recv": "受信データ",
	"websock.from": "差出人アドレス",
	"websock.state": "準備状態",
	"websock.numrecv": "受信データ数",
	"websock.nextrecv": "次の受信データ",
	"websock.closed": "接続が クローズしました！",
	webapi_call: "HTTP GET [URL]",
	json_parse: "JSON [JSON] 取出 [KEY]",
	json_stringify: "JSON [JSON] + [KEY] [VALUE]"
};
var translations = {
	en: en,
	ja: ja,
	"ja-Hira": {
	send_too_much: "そうしんが おおすぎなので、せつぞくをクローズしました！",
	"Websock.name": "ネットワークかくちょう",
	"websock.bind": "そうじゅしん ポート [PORT]",
	"websock.setname": "じぶんのアドレスを [TEXT] にする",
	"websock.close": "せつだん",
	"websock.send": "[TEXT] をそうしん",
	"websock.sendto": "[TEXT] を [SENDTO] に そうしん",
	"websock.whenrecv": "じゅしん したとき",
	"websock.recv": "じゅしん データ",
	"websock.from": "さしだしにんアドレス",
	"websock.state": "じゅんび じょうたい",
	"websock.numrecv": "じゅしんデータすう",
	"websock.nextrecv": "つぎの じゅしんデータ",
	"websock.closed": "せつぞくが クローズしました！",
	webapi_call: "HTTP GET [URL]",
	json_parse: "JSON [JSON] とりだし [KEY]",
	json_stringify: "JSON [JSON] + [KEY] [VALUE]"
}
};

var img = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAB3RJTUUH5wkMDhA5nwrrAAAAAMJJREFUWIXtmDEOwjAMRRtEFnqWrMAOnBrYgTUzvUW6ZAgTDMilkX9dDPKbIuVLeXJkK4orpTSaWXxbYAwTRDFBFBNEUS+4/LR5Pp5mmeK7w94N7f12BZ+stxuRw2+X62hGfQVNEEW9YFWTvBNCeK1jjJNlKVgV7FNq+pQmz1Kov2KW4KptRbIULMGcs0iWgiXovRfJUrCbRCJLwRoz964TyVL8ZxfPiQmiVDVJzcNSCvUVdPa7BWKCKCaIYoIoJojyAFP7MmCMkM/0AAAAAElFTkSuQmCC";

/**
 * Formatter which is used for translation.
 * This will be replaced which is used in the runtime.
 * @param {object} messageData - format-message object
 * @returns {string} - message for the locale
 */
var formatMessage = function formatMessage(messageData) {
  return messageData.defaultMessage;
};

/**
 * Setup format-message for this extension.
 */
var setupTranslations = function setupTranslations() {
  var localeSetup = formatMessage.setup();
  if (localeSetup && localeSetup.translations[localeSetup.locale]) {
    Object.assign(localeSetup.translations[localeSetup.locale], translations[localeSetup.locale]);
  }
};
var EXTENSION_ID = 'websockExt';

/**
 * URL to get this extension as a module.
 * When it was loaded as a module, 'extensionURL' will be replaced a URL which is retrieved from.
 * @type {string}
 */
var extensionURL = 'https://pcratch.j-code.org/xcratch-extensions/websock-ext/dist/websockExt.mjs';

/**
 * Scratch 3.0 blocks for example of Xcratch.
 */
var ExtensionBlocks = /*#__PURE__*/function () {
  /**
   * Construct a set of blocks for My Extension.
   * @param {Runtime} runtime - the Scratch 3.0 runtime.
   */
  function ExtensionBlocks(runtime) {
    var _this = this;
    _classCallCheck(this, ExtensionBlocks);
    /**
     * The Scratch 3.0 runtime.
     * @type {Runtime}
     */
    this.runtime = runtime;
    if (runtime.formatMessage) {
      // Replace 'formatMessage' to a formatter which is used in the runtime.
      formatMessage = runtime.formatMessage;
    }
    try {
      // ソケット作成とソケットの監視
      this.socket = null;
      this.sendData = [];
      this.recvData = [];
      this.currentData = {};
      this.readflag = false;
      this.wsockOpen = function () {
        _this.sendData = [];
        _this.recvData = [];
        _this.currentData = {};
        _this.readflag = false;
        if (_this.socket && _this.socket.readyState == 1) {
          // open
          return;
        }
        _this.socket = new WebSocket("wss://j-code.org/ws/");
        //console.log("new wsock:", this.wsock);
        // open this.socket
        _this.socket.addEventListener('open', function (e) {
          try {
            console.log('wsock-open:', _this.socket);
            _this.wsockAllSend(); // 接続待ちのパケットを送る
          } catch (error) {
            console.log(error);
          }
        });
        // close 終わり
        _this.socket.addEventListener('close', function (e) {
          try {
            //console.log("wsock-close!!:", this.socket )
            alert(formatMessage({
              id: "websock.closed",
              default: "せつぞくが クローズしました！"
            }));
          } catch (error) {
            console.log(error);
          }
        });
        // message サーバからのデータ受信時に呼ばれる
        _this.socket.addEventListener('message', function (e) {
          try {
            //console.log("recv message:", e.data)
            var msg = JSON.parse(e.data);
            if (msg && msg.MSGTYPE == "MESSAGE") {
              _this.recvData.push(msg);
              //console.log("message:", this.recvData.length)
            }

            if (msg && msg.MSGTYPE == "KEEPALIVE") {
              _this.socket.send(JSON.stringify({
                MSGTYPE: "KEEPALIVE"
              }));
              console.log("KEEPALIVE!!");
            }
          } catch (error) {
            console.log(error);
          }
        });
      };
      // 送信待ちデータを全部送信
      this.wsockAllSend = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/regenerator.mark(function _callee() {
        var msg;
        return regenerator.wrap(function _callee$(_context) {
          while (1) {
            switch (_context.prev = _context.next) {
              case 0:
                if (!(_this.sendData.length > 0 && _this.socket && _this.socket.readyState == 1)) {
                  _context.next = 19;
                  break;
                }
                if (!(_this.socket.bufferedAmount == 0)) {
                  _context.next = 7;
                  break;
                }
                //console.log("wsockAllSend:", this.sendData.length, this.socket.bufferedAmount)
                msg = _this.sendData.shift();
                _this.socket.send(msg);
                return _context.abrupt("return", 0);
              case 7:
                if (!(_this.sendData.length > 100)) {
                  _context.next = 14;
                  break;
                }
                console.log("buffer over 100!", _this.sendData.length, _this.socket.bufferedAmount);
                _this.socket.close();
                alert(formatMessage({
                  id: "send_too_much",
                  default: "そうしんが おおすぎ なので、接続をクローズしました！"
                }));
                return _context.abrupt("return", 0);
              case 14:
                console.log("sleep x ms:", _this.sendData.length, _this.socket.bufferedAmount);
                _context.next = 17;
                return new Promise(function (s) {
                  return setTimeout(s, _this.sendData.length * 5);
                });
              case 17:
                _context.next = 0;
                break;
              case 19:
              case "end":
                return _context.stop();
            }
          }
        }, _callee);
      }));
      // 準備状態
      this.wsockReadyState = function () {
        return _this.socket ? _this.socket.readyState : 0;
      };
      // 送信
      this.wsockSend = function (message) {
        _this.sendData.push(message);
        _this.wsockAllSend();
      };
    } catch (error) {
      console.log(error);
    }
  }
  /**
   * 送受信ポート
   * bind
   */
  _createClass(ExtensionBlocks, [{
    key: "websockBind",
    value: function websockBind(args) {
      try {
        this.wsockOpen();
        this.port = cast.toString(args.PORT);
        this.wsockSend(JSON.stringify({
          MSGTYPE: "BIND",
          room: this.port
        }));
      } catch (error) {
        console.log(error);
      }
    }
    /**
     * listen
     */
  }, {
    key: "websockListen",
    value: function websockListen(args) {
      try {
        this.wsockOpen();
        this.server = cast.toString(args.SERVER);
        this.port = cast.toString(args.PORT);
        //console.log("listen at ", this.server+this.port);
        // room に接続
        this.wsockSend(JSON.stringify({
          MSGTYPE: "LISTEN",
          room: this.server + this.port
        }));
      } catch (error) {
        console.log(error);
      }
    }
    /**
     * connect
     */
  }, {
    key: "websockConnect",
    value: function websockConnect(args) {
      try {
        this.wsockOpen();
        this.server = cast.toString(args.SERVER);
        this.port = cast.toString(args.PORT);
        //console.log("connect to ", this.server+this.port);
        this.wsockSend(JSON.stringify({
          MSGTYPE: "CONNECT",
          room: this.server + this.port
        }));
      } catch (error) {
        console.log(error);
      }
    }
    /**
     * name 名前を設定する
     * @param {TEXT} args - name to be given.
     */
  }, {
    key: "websockname",
    value: function websockname(args) {
      try {
        var text = cast.toString(args.TEXT);
        this.wsockSend(JSON.stringify({
          MSGTYPE: "NAME",
          name: text
        }));
      } catch (error) {
        console.log(error);
      }
    }
    /**
     * 切断
     * close
     * @param {TEXT} args - name to be given.
     */
  }, {
    key: "websockclose",
    value: function websockclose(args) {
      this.socket && this.socket.close();
    }
    /*
    【送受信】メッセージの送受信
    {
        MSGTYPE: "MESSAGE",
        sendto: "宛先ID"
            "": 差出人を除く全員に送る（sendto が無い場合、null の場合も同じ）
            "*": 差出人を含む全員に送る
        from: "送信元ID"（サービスが自動付加する）
        （その他は自由に利用）
    }
    */
    /**
     * 送信
     * Send Message.
     * @param {TEXT} args - the message to be sent.
     */
  }, {
    key: "websockSend",
    value: function websockSend(args) {
      try {
        var text = cast.toString(args.TEXT);
        //console.log("websockSend:", text);
        this.wsockSend(JSON.stringify({
          MSGTYPE: "MESSAGE",
          message: text
        }));
      } catch (error) {
        console.log(error);
      }
    }
    /**
     * 送信（アドレス指定）
     * Send Message.
     * @param {TEXT} args - the message to be sent.
     */
  }, {
    key: "websockSendTo",
    value: function websockSendTo(args) {
      try {
        var text = cast.toString(args.TEXT);
        var sendto = cast.toString(args.SENDTO);
        //console.log("websockSendto:", text);
        this.wsockSend(JSON.stringify({
          MSGTYPE: "MESSAGE",
          sendto: sendto,
          message: text
        }));
      } catch (error) {
        console.log(error);
      }
    }

    /**
     * 受信した時（イベント）
     * When data Recived.
     * @return {true} - data exist.
     */
  }, {
    key: "websockWhenRecv",
    value: function websockWhenRecv(args) {
      try {
        if (this.readflag || !this.recvData.length) {
          this.readflag = false;
          return false;
        }
        this.readflag = true;
        this.currentData = this.recvData.shift();
        //console.log("recv:", this.recvData.length, this.currentData);
        return true;
      } catch (error) {
        console.log(error);
        return false;
      }
    }
    /**
     * 受信データ
     * Read current message.
     * @return {Message} - string
     */
  }, {
    key: "websockRecv",
    value: function websockRecv() {
      try {
        return "" + this.currentData.message;
      } catch (error) {
        console.log(error);
        return "";
      }
    }
    /**
     * 差出人アドレス
     * Read current message.
     * @return {Message} - string
     */
  }, {
    key: "websockFrom",
    value: function websockFrom() {
      try {
        return "" + this.currentData.from;
      } catch (error) {
        console.log(error);
        return "";
      }
    }
    /**
     * 準備状態
     * Read current message.
     * @return {Message} - string
     */
  }, {
    key: "websockReadyState",
    value: function websockReadyState() {
      try {
        return 0 + this.wsockReadyState();
      } catch (error) {
        console.log(error);
        return 0;
      }
    }
    /**
     * 受信データ数
     * Number of recived.
     * @return {Number}
     */
  }, {
    key: "websockNumrecv",
    value: function websockNumrecv() {
      try {
        return 0 + this.recvData.length;
      } catch (error) {
        console.log(error);
        return 0;
      }
    }
    /**
     * 次の受信データ
     */
  }, {
    key: "websockNextrecv",
    value: function websockNextrecv(args) {
      try {
        if (this.recvData.length) {
          this.currentData = this.recvData.shift();
        }
      } catch (error) {
        console.log(error);
      }
    }

    /**
     * Web API Call
     */
  }, {
    key: "webapi_call",
    value: function () {
      var _webapi_call = _asyncToGenerator( /*#__PURE__*/regenerator.mark(function _callee2(args) {
        var url, response, s;
        return regenerator.wrap(function _callee2$(_context2) {
          while (1) {
            switch (_context2.prev = _context2.next) {
              case 0:
                _context2.prev = 0;
                url = cast.toString(args.URL);
                _context2.next = 4;
                return fetch(url);
              case 4:
                response = _context2.sent;
                _context2.next = 7;
                return response.text();
              case 7:
                s = _context2.sent;
                return _context2.abrupt("return", "" + s);
              case 11:
                _context2.prev = 11;
                _context2.t0 = _context2["catch"](0);
                console.log(_context2.t0);
                return _context2.abrupt("return", "{}");
              case 15:
              case "end":
                return _context2.stop();
            }
          }
        }, _callee2, null, [[0, 11]]);
      }));
      function webapi_call(_x) {
        return _webapi_call.apply(this, arguments);
      }
      return webapi_call;
    }()
    /**
     * json_stringfy
     */
  }, {
    key: "json_stringify",
    value: function json_stringify(args) {
      try {
        var json = cast.toString(args.JSON);
        var key = cast.toString(args.KEY);
        var value = cast.toString(args.VALUE);
        var j = JSON.parse(json);
        if (j.push && !key) {
          j.push(value);
        } else {
          j[key] = value;
        }
        //console.log("json_stringify:", j)
        var s = JSON.stringify(j);
        return "" + s;
      } catch (err) {
        console.log(err);
        return "{}";
      }
    }
    /**
     * json_parse
     */
  }, {
    key: "json_parse",
    value: function json_parse(args) {
      try {
        var json = cast.toString(args.JSON);
        var key = cast.toString(args.KEY);
        var j = JSON.parse(json);
        var val = j[key];
        if (_typeof$1(val) === "object") {
          val = JSON.stringify(val);
        }
        //console.log("json_parse:", val)
        return "" + val;
      } catch (err) {
        console.log(err);
        return "";
      }
    }

    /*
    doIt (args) {
        const func = new Function(`return (${Cast.toString(args.SCRIPT)})`);
        const result = func.call(this);
        console.log(result);
        return result;
    }
    */

    /**
     * @returns {object} metadata for this extension and its blocks.
     */

    //  TCP
    //  command listen(servername, port)  サーバーの接続待ち
    //  command connect(servername, port) クライアントからサーバーへ接続
    //  UDP
    //  command bind(port)
    //  IP
    //  command send()  全員へ（サーバーへ）
    //  event   recv()  誰かから
  }, {
    key: "getInfo",
    value: function getInfo() {
      setupTranslations();
      return {
        id: ExtensionBlocks.EXTENSION_ID,
        name: ExtensionBlocks.EXTENSION_NAME,
        extensionURL: ExtensionBlocks.extensionURL,
        blockIconURI: img,
        showStatusButton: false,
        blocks: [{
          // 送受信ポート
          // socket bind
          opcode: "websockBind",
          text: formatMessage({
            id: "websock.bind",
            default: "送受信 ポート [PORT]",
            description: "サーバーとして受信を待機します"
          }),
          blockType: blockType.COMMAND,
          arguments: {
            PORT: {
              type: argumentType.STRING,
              defaultValue: "7"
            }
          }
        }, {
          // 自分のアドレス
          opcode: "websockname",
          text: formatMessage({
            id: "websock.setname",
            default: "自分のアドレスを [TEXT] にする"
          }),
          blockType: blockType.COMMAND,
          arguments: {
            TEXT: {
              type: argumentType.STRING,
              defaultValue: "アドレス"
            }
          }
        }, {
          // 切断
          opcode: "websockclose",
          text: formatMessage({
            id: "websock.close",
            default: "切断"
          }),
          blockType: blockType.COMMAND,
          arguments: {}
        }, {
          // 送信
          opcode: "websockSend",
          text: formatMessage({
            id: "websock.send",
            default: "[TEXT] を送信"
          }),
          blockType: blockType.COMMAND,
          arguments: {
            TEXT: {
              type: argumentType.STRING,
              defaultValue: "hello"
            }
          }
        }, {
          // アドレスに送信
          opcode: "websockSendTo",
          text: formatMessage({
            id: "websock.sendto",
            default: "[SENDTO] に [TEXT] を送信"
          }),
          blockType: blockType.COMMAND,
          arguments: {
            SENDTO: {
              type: argumentType.STRING,
              defaultValue: "アドレス"
            },
            TEXT: {
              type: argumentType.STRING,
              defaultValue: "hello"
            }
          }
        }, {
          // 受信した時（イベント）
          opcode: "websockWhenRecv",
          text: formatMessage({
            id: "websock.whenrecv",
            default: "受信したとき"
          }),
          blockType: blockType.HAT,
          arguments: {},
          isEdgeActivated: true
        }, {
          // 受信データ
          opcode: "websockRecv",
          text: formatMessage({
            id: "websock.recv",
            default: "受信データ"
          }),
          blockType: blockType.REPORTER
        }, {
          // 差出人アドレス
          opcode: "websockFrom",
          text: formatMessage({
            id: "websock.from",
            default: "差出人アドレス"
          }),
          blockType: blockType.REPORTER
        }, {
          // 準備状態
          opcode: "websockReadyState",
          text: formatMessage({
            id: "websock.state",
            default: "準備状態"
          }),
          blockType: blockType.REPORTER
        }, {
          // 受信データ数
          opcode: "websockNumrecv",
          text: formatMessage({
            id: "websock.numrecv",
            default: "受信データ数"
          }),
          blockType: blockType.REPORTER
        }, {
          // 次の受信データ
          opcode: "websockNextrecv",
          text: formatMessage({
            id: "websock.nextrecv",
            default: "次の受信データ"
          }),
          blockType: blockType.COMMAND,
          arguments: {}
        }, {
          // Web API call
          opcode: "webapi_call",
          text: formatMessage({
            id: "webapi_call",
            default: "Web API 呼出 [URL]"
          }),
          blockType: blockType.REPORTER,
          arguments: {
            URL: {
              type: argumentType.STRING,
              defaultValue: "https://api.aoikujira.com/tenki/week.php?fmt=json"
            }
          }
        }, {
          // json_parse
          opcode: "json_parse",
          text: formatMessage({
            id: "json_parse",
            default: "JSON取出 [JSON] [KEY]"
          }),
          blockType: blockType.REPORTER,
          arguments: {
            JSON: {
              type: argumentType.STRING,
              defaultValue: '{}'
            },
            KEY: {
              type: argumentType.STRING,
              defaultValue: 'key'
            }
          }
        }, {
          // json_stringify
          opcode: "json_stringify",
          text: formatMessage({
            id: "json_stringify",
            default: "JSON追加 [JSON] [KEY] [VALUE]"
          }),
          blockType: blockType.REPORTER,
          arguments: {
            JSON: {
              type: argumentType.STRING,
              defaultValue: '{}'
            },
            KEY: {
              type: argumentType.STRING,
              defaultValue: 'key'
            },
            VALUE: {
              type: argumentType.STRING,
              defaultValue: 'value'
            }
          }
        }],
        menus: {}
      };
    }
  }], [{
    key: "EXTENSION_NAME",
    get:
    /**
     * @return {string} - the name of this extension.
     */
    function get() {
      return formatMessage({
        id: 'Websock.name',
        default: 'Websock Extension',
        description: 'Websock'
      });
    }

    /**
     * @return {string} - the ID of this extension.
     */
  }, {
    key: "EXTENSION_ID",
    get: function get() {
      return EXTENSION_ID;
    }

    /**
     * URL to get this extension.
     * @type {string}
     */
  }, {
    key: "extensionURL",
    get: function get() {
      return extensionURL;
    }

    /**
     * Set URL to get this extension.
     * The extensionURL will be changed to the URL of the loading server.
     * @param {string} url - URL
     */,
    set: function set(url) {
      extensionURL = url;
    }
  }]);
  return ExtensionBlocks;
}();

export { ExtensionBlocks as blockClass, entry };
