UNPKG

fleeta-api-lib

Version:

A comprehensive library for fleet management applications - API, Auth, Device management

1 lines 185 kB
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("zustand"),require("crypto-js")):"function"==typeof define&&define.amd?define(["exports","zustand","crypto-js"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).FleetAComponents={},e.zustand,e.CryptoJS)}(this,(function(e,t,n){"use strict";var i=Object.defineProperty,r=(e,t,n)=>((e,t,n)=>t in e?i(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n)(e,"symbol"!=typeof t?t+"":t,n);const s=t.create((e=>({config:null,isInitialized:!1,setConfig:t=>{e({config:t,isInitialized:!0})},clearConfig:()=>{e({config:null,isInitialized:!1})}})));function o(){const e=s.getState();return e.isInitialized&&e.config?e.config:null}function a(e){const t=o();return t?t[e]:null}function c(){const e=a("apiGateway");if(!e)throw new Error("API Gateway not configured. Please set VITE_API_GATEWAY in .env file.");return e}function l(){const e=a("iotApiGateway");if(!e)throw new Error("IoT API Gateway not configured. Please set VITE_IOT_API_GATEWAY in .env file.");return e}function h(){const e=a("eventWebSocketUrl");if(!e)throw new Error("Event WebSocket URL not configured. Please set VITE_EVENT_WEBSOCKET_URL in .env file.");return e}function d(e,t){let n;try{n=e()}catch(i){return}return{getItem:e=>{var t;const i=e=>null===e?null:JSON.parse(e,void 0),r=null!=(t=n.getItem(e))?t:null;return r instanceof Promise?r.then(i):i(r)},setItem:(e,t)=>n.setItem(e,JSON.stringify(t,void 0)),removeItem:e=>n.removeItem(e)}}const u=e=>t=>{try{const n=e(t);return n instanceof Promise?n:{then:e=>u(e)(n),catch(e){return this}}}catch(n){return{then(e){return this},catch:e=>u(e)(n)}}},p=(e,t)=>"getStorage"in t||"serialize"in t||"deserialize"in t?((e,t)=>(n,i,r)=>{let s={getStorage:()=>localStorage,serialize:JSON.stringify,deserialize:JSON.parse,partialize:e=>e,version:0,merge:(e,t)=>({...t,...e}),...t},o=!1;const a=new Set,c=new Set;let l;try{l=s.getStorage()}catch(E){}if(!l)return e(((...e)=>{n(...e)}),i,r);const h=u(s.serialize),d=()=>{const e=s.partialize({...i()});let t;const n=h({state:e,version:s.version}).then((e=>l.setItem(s.name,e))).catch((e=>{t=e}));if(t)throw t;return n},p=r.setState;r.setState=(e,t)=>{p(e,t),d()};const g=e(((...e)=>{n(...e),d()}),i,r);let m;const f=()=>{var e;if(!l)return;o=!1,a.forEach((e=>e(i())));const t=(null==(e=s.onRehydrateStorage)?void 0:e.call(s,i()))||void 0;return u(l.getItem.bind(l))(s.name).then((e=>{if(e)return s.deserialize(e)})).then((e=>{if(e){if("number"!=typeof e.version||e.version===s.version)return e.state;if(s.migrate)return s.migrate(e.state,e.version)}})).then((e=>{var t;return m=s.merge(e,null!=(t=i())?t:g),n(m,!0),d()})).then((()=>{null==t||t(m,void 0),o=!0,c.forEach((e=>e(m)))})).catch((e=>{null==t||t(void 0,e)}))};return r.persist={setOptions:e=>{s={...s,...e},e.getStorage&&(l=e.getStorage())},clearStorage:()=>{null==l||l.removeItem(s.name)},getOptions:()=>s,rehydrate:()=>f(),hasHydrated:()=>o,onHydrate:e=>(a.add(e),()=>{a.delete(e)}),onFinishHydration:e=>(c.add(e),()=>{c.delete(e)})},f(),m||g})(e,t):((e,t)=>(n,i,r)=>{let s={storage:d((()=>localStorage)),partialize:e=>e,version:0,merge:(e,t)=>({...t,...e}),...t},o=!1;const a=new Set,c=new Set;let l=s.storage;if(!l)return e(((...e)=>{n(...e)}),i,r);const h=()=>{const e=s.partialize({...i()});return l.setItem(s.name,{state:e,version:s.version})},p=r.setState;r.setState=(e,t)=>{p(e,t),h()};const g=e(((...e)=>{n(...e),h()}),i,r);let m;r.getInitialState=()=>g;const f=()=>{var e,t;if(!l)return;o=!1,a.forEach((e=>{var t;return e(null!=(t=i())?t:g)}));const r=(null==(t=s.onRehydrateStorage)?void 0:t.call(s,null!=(e=i())?e:g))||void 0;return u(l.getItem.bind(l))(s.name).then((e=>{if(e){if("number"!=typeof e.version||e.version===s.version)return[!1,e.state];if(s.migrate)return[!0,s.migrate(e.state,e.version)]}return[!1,void 0]})).then((e=>{var t;const[r,o]=e;if(m=s.merge(o,null!=(t=i())?t:g),n(m,!0),r)return h()})).then((()=>{null==r||r(m,void 0),m=i(),o=!0,c.forEach((e=>e(m)))})).catch((e=>{null==r||r(void 0,e)}))};return r.persist={setOptions:e=>{s={...s,...e},e.storage&&(l=e.storage)},clearStorage:()=>{null==l||l.removeItem(s.name)},getOptions:()=>s,rehydrate:()=>f(),hasHydrated:()=>o,onHydrate:e=>(a.add(e),()=>{a.delete(e)}),onFinishHydration:e=>(c.add(e),()=>{c.delete(e)})},s.skipHydration||f(),m||g})(e,t),g=t.create()(p((e=>({isAuthenticated:!1,userToken:null,jwtToken:null,serverConfig:null,userType:null,subscribeInfo:null,latestLoginInfo:null,error:null,setAuth:t=>{var n;if("BC_ERR_OK"===t.resultcode){const i=t.response||{},r=null==(n=i["logged in list"])?void 0:n.ids;e({isAuthenticated:!0,userToken:i.user_token??t.user_token??null,jwtToken:i.jsonwebtoken??t.jsonwebtoken??t.jwt_token??null,serverConfig:{was_server:i.was_server??"",was_port:i.was_port??"",gps_server:i.gps_server??"",gps_port:i.gps_port??"",gps_tracking_server:i.gps_tracking_server??"",gps_tracking_port:i.gps_tracking_port??"",geo_fence_server:i.geo_fence_server??"",geo_fence_port:i.geo_fence_port??""},userType:i.userType??null,subscribeInfo:i.subscribeinfo??null,latestLoginInfo:{timestamp:i.latestlogindt??"",mobileOS:i.lastMobileOS??"",appVersion:i.lastAppVer??"",webVersion:i.lastWebVer??"",duplicateLogins:r},error:null})}else e({error:t.message??"Login failed",isAuthenticated:!1})},clearAuth:()=>{e({isAuthenticated:!1,userToken:null,jwtToken:null,serverConfig:null,userType:null,subscribeInfo:null,latestLoginInfo:null,error:null})},setError:t=>e({error:t})})),{name:"auth-storage",skipHydration:!1})),m=["eng","deu","spa","fra","ind","ita","jpn","nor","rus","zho","tha","vie","kor","pol","nob","fin"],f={BC_ERR_AUTHENTICATION:"Authentication failed. Please check your credentials.",BC_ERR_SIGNATURE:"Invalid security signature. Please try again.",BC_ERR_INVALID_DATA:"Something went wrong. Please try again.",BC_ERR_INVALID_PARAMETER:"Invalid login parameters. Please check your input.",BC_ERR_NEED_TO_CONFIRM:"Please verify your email address before logging in.",BC_ERR_BLACK_LIST:"Your account has been blocked for security reasons. Please contact support.",BC_ERR_SERVER:"Server error. Please try again later.",BC_ERR_DUPLICATED:"Account is already logged in on another device.",BC_ERR_GOOGLEAPPLE_ACCOUNT:"This account uses Google or Apple sign-in. Please continue with one of those."},E={BC_ERR_AUTHENTICATION:"Authentication failed. Please try again.",BC_ERR_SIGNATURE:"Security verification failed. Please try again.",BC_ERR_INVALID_DATA:"Invalid data received. Please try again.",BC_ERR_ALREADY_REQUESTED:"Password reset email has already been sent. Please check your inbox.",BC_ERR_INVALID_PARAMETER:"Invalid request parameters. Please try again.",BC_ERR_SERVER:"Internal server error. Please try again later.",BC_ERR_NOT_FOUND:"Email address not found. Please check your email and try again."},v={BC_ERR_AUTHENTICATION:"BCS Token not exists",BC_ERR_INVALID_PARAMETER:"Invalid parameter",BC_ERR_SERVER:"Internal server error"},w={BC_ERR_AUTHENTICATION:"Registration authentication failed. Please try again.",BC_ERR_SIGNATURE:"Security verification failed. Please try again.",BC_ERR_INVALID_DATA:"Invalid registration data. Please check your information.",BC_ERR_INVALID_PARAMETER:"Invalid registration parameters. Please check your input.",BC_ERR_DUPLICATED:"This email address is already registered. Please use a different email or try logging in.",BC_ERR_BLACK_LIST:"This email address is blocked. Please contact support.",BC_ERR_SERVER:"Server error. Please try again later.",BC_ERR_NEED_TO_CONFIRM:"Please check your email for confirmation instructions.",BC_ERR_INVALID_INVITE_TOKEN:"Invalid invitation token. Please check the invitation link.",BC_ERR_EXPIRED_INVITE_TOKEN:"Invitation token has expired. Please request a new invitation."},S={BC_ERR_AUTHENTICATION:"Authentication failed. Please try again.",BC_ERR_SIGNATURE:"Security verification failed. Please try again.",BC_ERR_INVALID_DATA:"Invalid confirmation data. Please check your confirmation number.",BC_ERR_INVALID_PARAMETER:"Invalid confirmation parameters. Please check your input.",BC_ERR_SERVER:"Server error. Please try again later."};let C=!1,R=!1,A=!1;function y(){const e=navigator.platform.toLowerCase();return e.includes("win")?"win32":e.includes("mac")?"macos":e.includes("linux")?"linux":"web"}function T(){const e=navigator.userAgent;return!e.includes("Chrome")||e.includes("Edge")||e.includes("Edg")?e.includes("Firefox")?"Firefox":e.includes("Safari")&&!e.includes("Chrome")?"Safari":e.includes("Edge")||e.includes("Edg")?"Edge":e.includes("Opera")||e.includes("OPR")?"Opera":"Unknown Browser":"Chrome"}function _(){return-1*(new Date).getTimezoneOffset()}function b(){var e;const t=g.getState();return t.isAuthenticated&&t.userToken&&t.jwtToken&&(null==(e=t.subscribeInfo)?void 0:e.userEmail)?{userToken:t.userToken,userEmail:t.subscribeInfo.userEmail,jwtToken:t.jwtToken}:null}function I(){return null!==b()}function M(){const e=b();return!!e&&(e.userToken.length>0&&e.jwtToken.length>0&&e.userEmail.includes("@"))}function D(){const e=b();if(!e)throw new Error("Authentication required. Please login first.");return{Authorization:`Bearer ${e.jwtToken}`,"Content-Type":"application/json"}}function k(){return"Authentication required. Please login first."}function P(e){try{if(!Array.isArray(e))throw new Error("Devices must be an array");if(0===e.length)return{devicesByGroup:[],groupsByDevice:[],statistics:{total:0,online:0,offline:0,grouped:0,ungrouped:0,videoSharing:0,normalMode:0,parkingMode:0,wifiOnly:0,cloudEnabled:0,withBattery:0}};const t=function(e){if(!Array.isArray(e))throw new Error("Devices must be an array");const t=e.length,n=e.filter((e=>{var t;return"on"===(null==(t=null==e?void 0:e.device)?void 0:t.active)})).length,i=t-n,r=e.filter((e=>!!(null==e?void 0:e.groupManagementID))).length,s=t-r,o=e.filter((e=>{var t;return"on"===(null==(t=null==e?void 0:e.device)?void 0:t.share_video)})).length,a=e.filter((e=>{var t;return"0"===(null==(t=null==e?void 0:e.device)?void 0:t.mode)})).length,c=e.filter((e=>{var t;return"1"===(null==(t=null==e?void 0:e.device)?void 0:t.mode)})).length,l=e.filter((e=>{var t;return"wifi"===(null==(t=null==e?void 0:e.device)?void 0:t.reg_category)})).length,h=e.filter((e=>{var t;return"cloud"===(null==(t=null==e?void 0:e.device)?void 0:t.reg_category)})).length,d=e.filter((e=>{var t;return!!(null==(t=null==e?void 0:e.device)?void 0:t.battery)})).length,u={total:t,online:n,offline:i,grouped:r,ungrouped:s,videoSharing:o,normalMode:a,parkingMode:c,wifiOnly:l,cloudEnabled:h,withBattery:d};return u}(e),n=L(e),i=O(e);return{devicesByGroup:n,groupsByDevice:i,statistics:t}}catch(t){return{devicesByGroup:[],groupsByDevice:[],statistics:{total:0,online:0,offline:0,grouped:0,ungrouped:0,videoSharing:0,normalMode:0,parkingMode:0,wifiOnly:0,cloudEnabled:0,withBattery:0}}}}function N(e){return{...e,get groupId(){return this.groupManagementID}}}function U(e){return e.map((e=>N(e)))}function L(e){if(!Array.isArray(e))throw new Error("Devices must be an array");const t=new Map,n=new Map;e.forEach((e=>{if(!e||!e.device)return;const i=e.groupManagementID||"ungrouped",r=e.device.psn;t.has(i)||(t.set(i,[]),n.set(i,new Set));const s=n.get(i);s.has(r)||(s.add(r),t.get(i).push(e))}));const i=[];return t.forEach(((e,t)=>{const n=e[0];i.push({groupId:t,groupName:n.groupName||"Ungrouped",groupRegDate:n.groupRegDT,devices:e})})),i.sort(((e,t)=>"ungrouped"===e.groupId?-1:"ungrouped"===t.groupId?1:e.groupName.localeCompare(t.groupName))),i}function O(e){if(!Array.isArray(e))throw new Error("Devices must be an array");const t=new Map;e.forEach((e=>{(null==e?void 0:e.groupManagementID)&&(null==e?void 0:e.groupName)&&t.set(e.groupManagementID,{groupName:e.groupName,groupRegDate:e.groupRegDT})}));const n=new Map,i=new Set;e.forEach((e=>{if(!e||!e.device)return;const t=e.device.psn,r=e.groupManagementID||"ungrouped";n.has(t)||n.set(t,{device:e,groupIds:[]});const s=`${t}-${r}`;if(i.has(s))return;const o=n.get(t);o.groupIds.includes(r)||o.groupIds.push(r),i.add(s)}));const r=[];return n.forEach((({device:e,groupIds:n},i)=>{const s=n.map((e=>{const n=t.get(e);return{groupId:e,groupName:(null==n?void 0:n.groupName)||("ungrouped"===e?"Ungrouped":`Unknown Group (${e})`),groupRegDate:null==n?void 0:n.groupRegDate}}));r.push({psn:i,deviceName:e.device.dev_name||e.device.psn,device:e.device,assignedGroups:s,totalGroupsAssigned:n.length})})),r.sort(((e,t)=>e.psn.localeCompare(t.psn))),r}const B={BC_ERR_AUTHENTICATION:"Unauthorized - Authentication failed",BC_ERR_INVALID_PARAMETER:"Invalid parameter provided",BC_ERR_SERVER:"Internal server error occurred"},G={BC_ERR_AUTHENTICATION:"Unauthorized - Authentication failed",BC_ERR_INVALID_PARAMETER:"Invalid PSN parameter provided",BC_ERR_SERVER:"Internal server error occurred"},V={BC_ERR_AUTHENTICATION:"Unauthorized - Authentication failed",BC_ERR_INVALID_PARAMETER:"Invalid parameter provided",BC_ERR_SERVER:"Internal server error occurred",BC_ERR_DUPLICATED:"Duplicate device registration error",BC_ERR_BLACK_LIST:"Device registration blacklist - device is blocked"},$={BC_ERR_AUTHENTICATION:"Unauthorized - Authentication failed",BC_ERR_INVALID_PARAMETER:"Invalid parameter provided",BC_ERR_SERVER:"Internal server error occurred",BC_ERR_UNAVAILABLE:"Device not found - device may not be registered"},F={BC_ERR_AUTHENTICATION:"Unauthorized - Authentication failed",BC_ERR_INVALID_PARAMETER:"Invalid parameter provided",BC_ERR_SERVER:"Internal server error occurred",BC_ERR_DUPLICATED:"Device already registered - duplicate registration error",BC_ERR_BLACK_LIST:"Device registration blocked - device is blacklisted"},H={BC_ERR_AUTHENTICATION:"Unauthorized - Authentication failed",BC_ERR_INVALID_PARAMETER:"Invalid parameter provided",BC_ERR_INVALID_DATA:"Method not allowed",BC_ERR_SERVER:"Internal server error occurred"},q={BC_ERR_AUTHENTICATION:"Unauthorized - Authentication failed",BC_ERR_INVALID_PARAMETER:"Invalid parameter provided",BC_ERR_SERVER:"Internal server error occurred"},z={BC_ERR_INVALID_PARAMETER:"Invalid parameter provided",BC_ERR_INVALID_DATA:"Invalid data provided",BC_ERR_SERVER:"Internal server error occurred",BC_ERR_INVALID_PERMISSIONS:"Invalid permissions - Cloud feature not available for this firmware version"},x={BC_ERR_AUTHENTICATION:"Unauthorized - Authentication failed",BC_ERR_INVALID_PARAMETER:"Invalid parameter provided",BC_ERR_SERVER:"Internal server error occurred"},j={BC_ERR_AUTHENTICATION:"Unauthorized - Authentication failed",BC_ERR_INVALID_PARAMETER:"Invalid parameter provided",BC_ERR_SERVER:"Internal server error occurred"};async function W(e){const t=b();if(!t)throw new Error("Authentication required. Please login first.");try{const n=c(),i=new URLSearchParams;i.append("email",t.userEmail),i.append("user_token",t.userToken),i.append("tokenType","web"),(null==e?void 0:e.keyword)&&i.append("keyword",e.keyword),(null==e?void 0:e.startIndex)&&e.startIndex>=1&&i.append("startIndex",e.startIndex.toString()),(null==e?void 0:e.endIndex)&&e.endIndex>=1&&i.append("endIndex",e.endIndex.toString()),(null==e?void 0:e.psn)&&i.append("psn",e.psn);const r=await fetch(`${n}/DashCam/DeviceList?${i.toString()}`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t.jwtToken}`}});if(!r.ok)throw new Error(`HTTP error! status: ${r.status}`);const s=await r.json();if("BC_ERR_OK"!==s.resultcode){throw new Error(B[s.resultcode]||s.message||"Unknown error occurred")}s.response||(s.response={deviceCount:0,deviceLimitCount:0,sharedEventMap:"off",deviceListInfo:[]}),s.response.deviceListInfo||(s.response.deviceListInfo=[]);const{devicesByGroup:o,groupsByDevice:a,statistics:l}=P(s.response.deviceListInfo),h=U(s.response.deviceListInfo);return{resultcode:s.resultcode,message:s.message,response:{deviceCount:s.response.deviceCount||0,deviceLimitCount:s.response.deviceLimitCount||0,sharedEventMap:s.response.sharedEventMap||"off",deviceListInfo:h},groupedData:{devicesByGroup:o,groupsByDevice:a,statistics:l}}}catch(n){throw n}}async function K(e){const t=b();if(!t)throw new Error("Authentication required. Please login first.");try{const n=c(),i=new URLSearchParams;i.append("psn",e.psn);const r=await fetch(`${n}/DashCam/DeviceList/status?${i.toString()}`,{method:"GET",headers:{Authorization:`Bearer ${t.jwtToken}`}});if(!r.ok)throw new Error(`HTTP error! status: ${r.status}`);const s=await r.json();if("BC_ERR_OK"!==s.resultcode){throw new Error(G[s.resultcode]||s.message||"Unknown error occurred")}return s}catch(n){throw n}}async function Q(e){const t=b();if(!t)throw new Error("Authentication required. Please login first.");try{const n=c(),i={email:t.userEmail,user_token:t.userToken,tokenType:"web",...e};if(!i.psn||0===i.psn.trim().length)throw new Error("PSN is required");if(i.regCategory&&!["wifi","cloud"].includes(i.regCategory))throw new Error('Invalid regCategory. Must be "wifi" or "cloud"');if(i.communication_identifier&&!["Wifi","Cat4","Cat-M1"].includes(i.communication_identifier))throw new Error('Invalid communication_identifier. Must be "Wifi", "Cat4", or "Cat-M1"');if(["share_leu_bigdata","agree_gps","share_gps","share_video","share_audio","share_dev_name"].forEach((e=>{const t=i[e];if(void 0!==t&&!["on","off"].includes(t))throw new Error(`Invalid ${e}. Must be "on" or "off"`)})),void 0!==i.hotspot){if("object"!=typeof i.hotspot)throw new Error("Hotspot must be an object or empty object {}");if(0===Object.keys(i.hotspot).length);else{const e=i.hotspot;if(void 0!==e.sta_ssid&&"string"!=typeof e.sta_ssid)throw new Error("hotspot.sta_ssid must be a string");if(void 0!==e.sta_pw&&"string"!=typeof e.sta_pw)throw new Error("hotspot.sta_pw must be a string (encrypted data)")}}const r=await fetch(`${n}/DashCam/DeviceList`,{method:"PUT",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t.jwtToken}`},body:JSON.stringify(i)});if(!r.ok)throw new Error(`HTTP error! status: ${r.status}`);const s=await r.json();if("BC_ERR_OK"!==s.resultcode){throw new Error(V[s.resultcode]||s.message||"Unknown error occurred")}return s}catch(n){throw n}}async function Z(e){const t=b();if(!t)throw new Error("Authentication required. Please login first.");try{const n=c(),i={email:t.userEmail,user_token:t.userToken,tokenType:"web",...e};if(!i.psn||0===i.psn.trim().length)throw new Error("PSN is required");if(!i.regCategory||!["wifi","cloud"].includes(i.regCategory))throw new Error('Invalid regCategory. Must be "wifi" or "cloud"');const r=await fetch(`${n}/DashCam/DeviceList`,{method:"DELETE",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t.jwtToken}`},body:JSON.stringify(i)});if(!r.ok)throw new Error(`HTTP error! status: ${r.status}`);const s=await r.json();if("BC_ERR_OK"!==s.resultcode){throw new Error($[s.resultcode]||s.message||"Unknown error occurred")}return s}catch(n){throw n}}async function J(e){const t=b();if(!t)throw new Error("Authentication required. Please login first.");try{const n=c(),i={email:t.userEmail,user_token:t.userToken,tokenType:"web",companyID:"",...e};if(!i.psn||0===i.psn.trim().length)throw new Error("PSN is required");if(!i.cldn||0===i.cldn.trim().length)throw new Error("CLDN (Cloud Number) is required");if(!i.dev_name||0===i.dev_name.trim().length)throw new Error("Device name is required");if(!i.regCategory||!["wifi","cloud"].includes(i.regCategory))throw new Error('Registration category is required and must be "wifi" or "cloud"');if(!i.ap_ssid||0===i.ap_ssid.trim().length)throw new Error("Access Point SSID is required");if(!i.ap_pw||0===i.ap_pw.trim().length)throw new Error("Access Point password is required");if(!i.model||0===i.model.trim().length)throw new Error("Device model is required");if(!i.agree_gps||!["on","off"].includes(i.agree_gps))throw new Error('GPS agreement is required and must be "on" or "off"');if(i.shareLeuBigdata&&!["on","off"].includes(i.shareLeuBigdata))throw new Error('Share LEU bigdata must be "on" or "off"');const r=await fetch(`${n}/DashCam/DeviceList`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t.jwtToken}`},body:JSON.stringify(i)});if(!r.ok)throw new Error(`HTTP error! status: ${r.status}`);const s=await r.json();if("BC_ERR_OK"!==s.resultcode){throw new Error(F[s.resultcode]||s.message||"Unknown error occurred")}return s}catch(n){throw n}}async function Y(e){const t=b();if(!t)throw new Error("Authentication required. Please login first.");try{const n=c();if(!e.psn||"string"!=typeof e.psn)throw new Error("PSN is required and must be a string");if(0===e.psn.trim().length)throw new Error("PSN is required");if(!e.devName||0===e.devName.trim().length)throw new Error("Device name is required");if(!e.version||!["1","2"].includes(e.version))throw new Error('Version is required and must be "1" or "2"');if(e.file&&!(e.file instanceof File))throw new Error("File must be a File object");const i=t.userEmail,r=t.userToken,s=new FormData;e.file&&s.append("file",e.file);s.append("body",JSON.stringify({email:i,user_token:r,psn:e.psn,devName:e.devName,version:e.version}));const o=await fetch(`${n}/Account/CameraProfile`,{method:"POST",headers:{Authorization:`Bearer ${t.jwtToken}`},body:s});if(!o.ok)throw new Error(`HTTP error! status: ${o.status}`);const a=await o.json();if("BC_ERR_OK"!==a.resultcode){throw new Error(j[a.resultcode]||a.message||"Unknown error occurred")}return a}catch(n){throw n}}const X=5,ee=20,te=["Seoul Fleet Alpha","Busan Transport Beta","Daegu Logistics Gamma","Incheon Delivery Delta","Gwangju Express Epsilon"],ne=["DR970X-2CH","DR970X-1CH","DR900X-2CH","DR900X-1CH","DR750X-2CH"],ie=["Wifi","Cat4","Cat-M1"];function re(){const e=Math.floor(100*Math.random()),t=Math.floor(60*Math.random())+10;return{ssid:`MOCK_BATTERY_${Math.random().toString(36).substr(2,9)}`,celsius:t,battery_percent:e,createdAt:new Date(Date.now()-6048e5*Math.random()).toISOString(),updatedAt:(new Date).toISOString(),state:e>70?"latest":e>30?"lateup1":"lateup2"}}function se(e,t,n){const i=function(e,t){return`MOCK${(e+1).toString().padStart(2,"0")}${(t+1).toString().padStart(3,"0")}`}(e,t),r=Math.random()>.3,s=Math.random()>.4,o=Math.random()>.5,a=Math.random()>.8,c=new Date,l=new Date(c.getTime()-31536e6*Math.random()),h=r?new Date(c.getTime()-864e5*Math.random()):new Date(c.getTime()-2592e6*Math.random());return{valid:"valid",psn:i,model:ne[Math.floor(Math.random()*ne.length)],active:r?"on":"off",dev_name:`${n.split(" ")[0]}-${(t+1).toString().padStart(3,"0")}`,battery:Math.random()>.2?re():void 0,lb_server_name:`mock-lb-${Math.floor(10*Math.random())}`,lb_http_port:80,lb_rtmp_port:1935,share_video:s?"on":"off",share_audio:s&&Math.random()>.5?"on":"off",share_dev_name:"on",share_gps:r?"on":"off",agree_gps:"on",fw_ver:`${Math.floor(3*Math.random())+1}.${Math.floor(10*Math.random())}.${Math.floor(100*Math.random())}`,upload_server:o?`cloud-upload-${Math.floor(5*Math.random())}.fleeta.io`:void 0,upload_port:o?443:void 0,lang:"eng",mode:a?"1":"0",communication_identifier:ie[Math.floor(Math.random()*ie.length)],temperature_level:Math.floor(5*Math.random())+1,sensitivity_level:Math.floor(5*Math.random())+1,dms_type:"standard",dms_version:"1.0.0",reg_date:l.toISOString(),login_date:h.toISOString(),iot_conn:r?"on":"off",reg_category:o?"cloud":"wifi",continentCode:"AS",countryCode:"KR",ip:`192.168.${Math.floor(255*Math.random())}.${Math.floor(255*Math.random())}`,liveview_rating:Math.floor(5*Math.random())+1,regInfoUpdateDT:(new Date).toISOString(),countryCodeUpdateDT:(new Date).toISOString(),profile_img:Math.random()>.7?`https://api.dicebear.com/7.x/identicon/svg?seed=${i}`:void 0,profile_img_v2:Math.random()>.7?`https://api.dicebear.com/7.x/avataaars/svg?seed=${i}`:void 0,cldn:`cldn_${i.toLowerCase()}`,ap_ssid:o?void 0:`MockWiFi_${t}`,ap_pw:o?void 0:`mock_pass_${t}`,require_time_sync:Math.random()>.5?"on":"off"}}function oe(){const e=[];for(let t=0;X>t;t++){const n=te[t],i=`MOCK_GROUP_${(t+1).toString().padStart(3,"0")}`,r=new Date(Date.now()-31536e6*Math.random()).toISOString();for(let s=0;ee>s;s++){const o=N({groupManagementID:i,groupName:n,groupRegDT:r,device:se(t,s,n)});e.push(o)}}return e}const ae={BC_ERR_AUTHENTICATION:"Authentication failed. Please check your credentials.",BC_ERR_INVALID_PARAMETER:"Invalid parameters provided.",BC_ERR_SERVER:"Internal server error occurred.",BC_ERR_UNAVAILABLE:"Device is not available for live streaming.",BC_ERR_BUSY:"Device is currently busy with another live stream.",BC_ERR_UNPLUGED:"Device is unplugged and cannot stream video."};let ce=new Set;async function le(e){const t=b();if(!t)throw new Error("Authentication required. Please login first.");const n=`${e.psn}-${e.param1||"1"}`;if(ce.has(n))throw new Error("PlayLiveView request already in progress for this device");try{ce.add(n);const i=l(),r={command:"PlayLiveView",email:t.userEmail,user_token:t.userToken,tokenType:e.tokenType||"web",psn:e.psn,param1:e.param1||"1"},s=await fetch(`${i}/IoT/devicecommand`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t.jwtToken}`},body:JSON.stringify(r)});if(!s.ok)throw new Error(`HTTP error! status: ${s.status}`);const o=await s.json();if("BC_ERR_AUTHENTICATION"===o.resultcode)throw new Error("Authentication failed");if("BC_ERR_OK"!==o.resultcode){throw new Error(ae[o.resultcode]||o.message||"Unknown error occurred")}return o}catch(i){throw i}finally{ce.delete(n)}}async function he(e){const t=b();if(!t)throw new Error("Authentication required. Please login first.");try{const n=l(),i=await fetch(`${n}/IoT/devicecommand`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t.jwtToken}`},body:JSON.stringify({command:"StopLiveView",email:t.userEmail,user_token:t.userToken,tokenType:e.tokenType||"web",psn:e.psn})});if(!i.ok)throw new Error(`HTTP error! status: ${i.status}`);const r=await i.json();if("BC_ERR_AUTHENTICATION"===r.resultcode)throw new Error("Authentication failed");if("BC_ERR_OK"!==r.resultcode){throw new Error(ae[r.resultcode]||r.message||"Unknown error occurred")}return r}catch(n){throw n}}async function de(e){const t=b();if(!t)throw new Error("Authentication required. Please login first.");try{const n=l(),i={command:"LiveDirection",email:t.userEmail,user_token:t.userToken,tokenType:"web",psn:e.psn,param1:e.param1},r=await fetch(`${n}/IoT/devicecommand`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t.jwtToken}`},body:JSON.stringify(i)});if(!r.ok)throw new Error(`HTTP error! status: ${r.status}`);const s=await r.json();if("BC_ERR_AUTHENTICATION"===s.resultcode)throw new Error("Authentication failed");if("BC_ERR_OK"!==s.resultcode){throw new Error(ae[s.resultcode]||s.message||"Unknown error occurred")}return s}catch(n){throw n}}async function ue(e,t=1,n=3e3){let i=0;for(;t>i;)try{const r=await de(e);if("busy"===r.status&&t-1>i){await new Promise((e=>setTimeout(e,n))),i++;continue}return r}catch(r){if(i>=t-1)throw r;await new Promise((e=>setTimeout(e,n))),i++}throw new Error(`Failed to change live direction after ${t} attempts`)}async function pe(e){const t=b();if(!t)throw new Error("Authentication required. Please login first.");try{const n=c(),i=await fetch(`${n}/CloudService/LivePresignURL`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t.jwtToken}`},body:JSON.stringify(e)});if(!i.ok)throw new Error(`HTTP error! status: ${i.status}`);const r=await i.json();if("BC_ERR_OK"!==r.resultcode){throw new Error("BC_ERR_TIMEOUT"===r.resultcode?"Request timeout - please try again":"BC_ERR_AUTHENTICATION"===r.resultcode?"Authentication failed":"BC_ERR_SERVER"===r.resultcode?"Internal server error":r.message||"Unknown error occurred")}return r}catch(n){throw n}}async function ge(e,t="1",n,i="VIEWER"){try{if("onLiveStreaming"===(await le({psn:e,param1:t})).status)throw new Error("Device is currently streaming to another client. Please try again later.");const r=`${e}_live`,s=await pe({streamName:r,role:i,psn:e});if(!(s.region&&s.channelARN&&s.url&&s.iceServers&&s.endpointsByProtocol))throw new Error("Incomplete WebRTC configuration received");return{region:s.region,channelARN:s.channelARN,url:s.url,iceServers:s.iceServers,endpointsByProtocol:s.endpointsByProtocol,role:i,clientId:n||e}}catch(r){throw r}}async function me(e){const t=b();if(!t)throw new Error("Authentication required. Please login first.");try{const n=l(),i={command:"TwoWayStart",email:t.userEmail,user_token:t.userToken,tokenType:e.tokenType||"web",psn:e.psn},r=await fetch(`${n}/IoT/devicecommand`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t.jwtToken}`},body:JSON.stringify(i)});if(!r.ok)throw new Error(`HTTP error! status: ${r.status}`);const s=await r.json();if("BC_ERR_AUTHENTICATION"===s.resultcode)throw new Error("Authentication failed");if("BC_ERR_OK"!==s.resultcode){throw new Error(ae[s.resultcode]||s.message||"Unknown error occurred")}return s}catch(n){throw n}}async function fe(e){const t=b();if(!t)throw new Error("Authentication required. Please login first.");try{const n=l(),i={command:"TwoWayStop",email:t.userEmail,user_token:t.userToken,tokenType:e.tokenType||"web",psn:e.psn},r=await fetch(`${n}/IoT/devicecommand`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t.jwtToken}`},body:JSON.stringify(i)});if(!r.ok)throw new Error(`HTTP error! status: ${r.status}`);const s=await r.json();if("BC_ERR_AUTHENTICATION"===s.resultcode)throw new Error("Authentication failed");if("BC_ERR_OK"!==s.resultcode){throw new Error(ae[s.resultcode]||s.message||"Unknown error occurred")}return s}catch(n){throw n}}class Ee{constructor(e,t){r(this,"config"),r(this,"webrtcConfig",null),r(this,"provider"),r(this,"connectionId"),r(this,"audioManager"),r(this,"stateMachine"),r(this,"dependencies"),r(this,"error",null),r(this,"peerConnection",null),r(this,"signalingClient",null),r(this,"stream",null),r(this,"receivedStreams",new Set),r(this,"connectionEstablished",!1),r(this,"audioRenegotiationInProgress",!1),r(this,"lastOfferCreationTime",0),r(this,"stats",null),r(this,"statsInterval",null),r(this,"eventHandlers",{}),r(this,"rtpMonitor",null),r(this,"lastAudioBytesSent",0),r(this,"lastAudioBytesReceived",0),this.config=e,this.provider=e.provider,this.connectionId=`${e.deviceId}_${e.channel}_${Date.now()}`,this.audioManager=t.audioManager,this.stateMachine=t.stateMachine,this.dependencies=t.dependencies,this.stateMachine.setCallbacks({onStateChange:(e,t,n)=>{var i,r;null==(r=(i=this.eventHandlers).onStateChange)||r.call(i,e)},onInvalidTransition:(e,t)=>{}}),e.onStateChange&&(this.eventHandlers.onStateChange=e.onStateChange),e.onError&&(this.eventHandlers.onError=e.onError),e.onStreamReceived&&(this.eventHandlers.onStreamReceived=e.onStreamReceived),e.onStatsUpdate&&(this.eventHandlers.onStatsUpdate=e.onStatsUpdate)}async connect(){if("connecting"!==this.stateMachine.getState()&&"connected"!==this.stateMachine.getState())try{if(this.stateMachine.transition("CONNECT"),this.setError(null),!this.dependencies.webrtcSDK){const e="undefined"!=typeof window?window.KVSWebRTC:null;if(!e)throw new Error("WebRTC SDK not available. Please ensure SDK is loaded before creating connection.");this.dependencies.webrtcSDK=e}if(this.config.webrtcConfig)this.webrtcConfig=this.config.webrtcConfig;else{const e={deviceId:this.config.deviceId,channel:this.config.channel,clientId:this.config.clientId||this.config.deviceId,role:this.config.role||"VIEWER"};this.webrtcConfig=await this.provider.getWebRTCConfig(e)}await this.initializeWebRTCConnection(this.webrtcConfig),this.config.enableStats&&this.startStatsMonitoring()}catch(e){const t=e instanceof Error?e:new Error("Connection failed");throw this.setError(t),this.stateMachine.transition("ERROR"),t}}async disconnect(){try{if(this.stopStatsMonitoring(),this.receivedStreams.clear(),this.connectionEstablished=!1,this.stream=null,this.peerConnection&&(this.peerConnection.close(),this.peerConnection=null),this.signalingClient){try{this.signalingClient.close()}catch(e){}this.signalingClient=null}try{await this.provider.stopStreaming(this.config.deviceId)}catch(e){}this.webrtcConfig=null,this.stats=null,this.stateMachine.transition("DISCONNECT")}catch(e){this.stateMachine.transition("DISCONNECT")}}async changeChannel(e){const t=this.stateMachine.getState();if(e!==this.config.channel&&"connecting"!==t&&"idle"!==t)try{this.stateMachine.transition("CHANNEL_CHANGE_START"),this.receivedStreams.clear(),this.stream=null,await this.provider.changeChannel(this.config.deviceId,e),this.config.channel=e,this.stateMachine.transition("CHANNEL_CHANGE_COMPLETE")}catch(n){const t=new Error(`Channel ${e} is not available`);throw this.setError(t),"connected"===this.stateMachine.getState()&&this.stateMachine.transition("CHANNEL_CHANGE_COMPLETE"),t}}async startTwoWayAudio(){if(!this.peerConnection||"connected"!==this.stateMachine.getState())throw new Error("WebRTC connection not established");if(await this.audioManager.startTwoWayAudio(this.peerConnection),!this.peerConnection.localDescription||!this.signalingClient)throw new Error("Cannot send audio offer - signaling not ready");try{this.signalingClient.sendSdpOffer(this.peerConnection.localDescription)}catch(e){throw new Error(`Failed to send audio offer: ${e instanceof Error?e.message:"Unknown error"}`)}}async stopTwoWayAudio(){await this.audioManager.stopTwoWayAudio(this.peerConnection||void 0)}setLocalAudioEnabled(e){this.audioManager.setLocalAudioEnabled(e)}getLocalAudioStream(){return this.audioManager.getLocalAudioStream()}getRemoteAudioStream(){return this.stream}getState(){return this.stateMachine.getState()}getConfig(){return this.webrtcConfig}getStats(){return this.stats}getError(){return this.error}on(e,t){this.eventHandlers[e]=t}off(e,t){this.eventHandlers[e]===t&&delete this.eventHandlers[e]}destroy(){if(this.audioManager.cleanup(),this.stopRTPMonitoring(),this.stopStatsMonitoring(),this.peerConnection&&(this.peerConnection.close(),this.peerConnection=null),this.signalingClient){try{this.signalingClient.close()}catch(e){}this.signalingClient=null}this.receivedStreams.clear(),this.connectionEstablished=!1,this.eventHandlers={},this.webrtcConfig=null,this.stats=null,this.stateMachine.reset()}async initializeWebRTCConnection(e){try{const t={getSignedURL:()=>e.url},n=new RTCPeerConnection({iceServers:e.iceServers.map((e=>({urls:e.urls,username:e.username,credential:e.credential})))});this.peerConnection=n;const i=new this.dependencies.webrtcSDK.SignalingClient({requestSigner:t,region:e.region,role:this.dependencies.webrtcSDK.Role.VIEWER,clientId:e.clientId,channelARN:e.channelARN,channelEndpoint:e.endpointsByProtocol.WSS});this.signalingClient=i,n.ontrack=this._handleTrackEvent.bind(this),n.oniceconnectionstatechange=()=>{const e=this.stateMachine.getState();switch(n.iceConnectionState){case"connected":case"completed":this.connectionEstablished||"connected"===e||(this.connectionEstablished=!0,this.stateMachine.transition("CONNECTION_ESTABLISHED"),this.startRTPMonitoring(n));break;case"disconnected":case"closed":"connected"===e&&this.stateMachine.canTransition("CHANNEL_CHANGE_START")||(this.connectionEstablished=!1,this.stateMachine.transition("DISCONNECT"));break;case"failed":if("connected"!==e||!this.stateMachine.canTransition("CHANNEL_CHANGE_START")){this.connectionEstablished=!1;const e=new Error("ICE connection failed");this.setError(e),this.stateMachine.transition("ERROR")}}},i.on("open",(async()=>{try{const e=await n.createOffer({offerToReceiveAudio:!0,offerToReceiveVideo:!0});await n.setLocalDescription(e),i.sendSdpOffer(n.localDescription)}catch(e){const t=e instanceof Error?e:new Error("Failed to create SDP offer");this.setError(t),this.stateMachine.transition("ERROR")}})),i.on("sdpAnswer",(async e=>{var t,i,r,s;const o=Date.now()-this.lastOfferCreationTime;try{const a=this.audioRenegotiationInProgress&&1e4>o&&"offer"===(null==(t=n.localDescription)?void 0:t.type)&&(null==(r=null==(i=n.localDescription)?void 0:i.sdp)?void 0:r.includes("m=audio"))&&(null==(s=e.sdp)?void 0:s.includes("m=audio"));await n.setRemoteDescription(e),a&&(this.audioRenegotiationInProgress=!1,n.__audioRenegotiationInProgress=!1)}catch(a){const e=a instanceof Error?a:new Error("Failed to set remote description");this.setError(e),this.stateMachine.transition("ERROR")}})),i.on("iceCandidate",(async e=>{try{await n.addIceCandidate(e)}catch(t){}})),n.onicecandidate=({candidate:e})=>{e&&i.sendIceCandidate(e)},i.on("close",(()=>{this.stateMachine.canTransition("CHANNEL_CHANGE_START")||this.stateMachine.transition("DISCONNECT")})),i.on("error",(e=>{if(!this.stateMachine.canTransition("CHANNEL_CHANGE_START")){const t=new Error(`Signaling error: ${e.message}`);this.setError(t),this.stateMachine.transition("ERROR")}})),i.open()}catch(t){throw t}}startStatsMonitoring(){this.statsInterval&&clearInterval(this.statsInterval);this.statsInterval=setInterval((async()=>{var e,t;if(this.peerConnection&&"connected"===this.stateMachine.getState())try{const n=await this.peerConnection.getStats();let i=0,r=0,s=0,o=0,a=0;n.forEach((e=>{"inbound-rtp"===e.type&&"video"===e.mediaType&&(i+=e.bytesReceived||0,r+=e.packetsReceived||0,s+=e.packetsLost||0,o=e.jitter||0),"candidate-pair"===e.type&&"succeeded"===e.state&&(a=e.currentRoundTripTime||0)})),this.stats={bytesReceived:i,packetsReceived:r,packetsLost:s,jitter:o,roundTripTime:a},null==(t=(e=this.eventHandlers).onStatsUpdate)||t.call(e,this.stats)}catch(n){}}),this.config.statsInterval||2e3)}stopStatsMonitoring(){this.statsInterval&&(clearInterval(this.statsInterval),this.statsInterval=null)}setError(e){var t,n;this.error=e,e&&(null==(n=(t=this.eventHandlers).onError)||n.call(t,e))}_handleTrackEvent(e){var t,n;if(e.streams[0]){const i=e.streams[0].id,r=e.streams[0];!this.receivedStreams.has(i)?(this.receivedStreams.add(i),this.stream=r,r.getAudioTracks().forEach(((e,t)=>{})),null==(n=(t=this.eventHandlers).onStreamReceived)||n.call(t,r),this.connectionEstablished||"connected"===this.stateMachine.getState()||(this.connectionEstablished=!0,this.stateMachine.transition("CONNECTION_ESTABLISHED"))):this.stream=r}}startRTPMonitoring(e){this.rtpMonitor&&clearInterval(this.rtpMonitor),this.rtpMonitor=setInterval((async()=>{try{const t=await e.getStats();let n=!1,i=!1;t.forEach((e=>{if("outbound-rtp"===e.type&&"audio"===e.mediaType){const t=e.bytesSent||0;t>this.lastAudioBytesSent&&(n=!0),this.lastAudioBytesSent=t}if("inbound-rtp"===e.type&&"audio"===e.mediaType){const t=e.bytesReceived||0;t>this.lastAudioBytesReceived&&(i=!0),this.lastAudioBytesReceived=t}}))}catch(t){}}),2e3)}stopRTPMonitoring(){this.rtpMonitor&&(clearInterval(this.rtpMonitor),this.rtpMonitor=null)}}class ve{constructor(e={}){r(this,"localAudioStream",null),r(this,"isLocalAudioEnabled",!0),r(this,"isTwoWayActive",!1),r(this,"audioConfig"),r(this,"audioTrackMonitor",null),this.audioConfig={echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0,...e}}async startTwoWayAudio(e){if(!this.isTwoWayActive){if(!e)throw new Error("Peer connection is required for two-way audio");try{this.localAudioStream=await navigator.mediaDevices.getUserMedia({audio:{echoCancellation:this.audioConfig.echoCancellation,noiseSuppression:this.audioConfig.noiseSuppression,autoGainControl:this.audioConfig.autoGainControl,sampleRate:this.audioConfig.sampleRate,channelCount:this.audioConfig.channelCount},video:!1}),this.localAudioStream.getAudioTracks().forEach((t=>{e.addTrack(t,this.localAudioStream),t.onended=()=>{},t.onmute=()=>{},t.onunmute=()=>{}})),await this.renegotiateForAudio(e),this.isTwoWayActive=!0,this.startAudioTransmissionMonitoring(e)}catch(t){throw this.localAudioStream&&(this.localAudioStream.getTracks().forEach((e=>e.stop())),this.localAudioStream=null),new Error(`Failed to start two-way audio: ${t instanceof Error?t.message:"Unknown error"}`)}}}async stopTwoWayAudio(e){if(this.isTwoWayActive)try{if(this.localAudioStream&&(this.localAudioStream.getTracks().forEach((e=>{e.stop()})),this.localAudioStream=null),this.stopAudioTransmissionMonitoring(),e){const t=e.getSenders().filter((e=>e.track&&"audio"===e.track.kind));for(const n of t)await e.removeTrack(n)}this.isTwoWayActive=!1}catch(t){}finally{this.isTwoWayActive=!1}}setLocalAudioEnabled(e){this.localAudioStream&&(this.localAudioStream.getAudioTracks().forEach((t=>{t.enabled=e})),this.isLocalAudioEnabled=e)}getLocalAudioStream(){return this.localAudioStream}isTwoWayAudioActive(){return this.isTwoWayActive}isLocalAudioMuted(){return!this.isLocalAudioEnabled}updateConfig(e){this.audioConfig={...this.audioConfig,...e}}cleanup(){this.stopAudioTransmissionMonitoring(),this.localAudioStream&&(this.localAudioStream.getTracks().forEach((e=>e.stop())),this.localAudioStream=null),this.isTwoWayActive=!1,this.isLocalAudioEnabled=!0}async renegotiateForAudio(e){if(!e)throw new Error("Peer connection not available for renegotiation");try{const t=await e.createOffer({offerToReceiveAudio:!0,offerToReceiveVideo:!0});await e.setLocalDescription(t),this.markAudioRenegotiationInProgress(e)}catch(t){throw t}}startAudioTransmissionMonitoring(e){this.audioTrackMonitor&&clearInterval(this.audioTrackMonitor),this.audioTrackMonitor=setInterval((async()=>{if(e&&"connected"===e.connectionState)try{(await e.getStats()).forEach((e=>{}))}catch(t){}}),2e3)}stopAudioTransmissionMonitoring(){this.audioTrackMonitor&&(clearInterval(this.audioTrackMonitor),this.audioTrackMonitor=null)}markAudioRenegotiationInProgress(e){e.__audioRenegotiationInProgress=!0,e.__lastOfferCreationTime=Date.now()}}class we{constructor(e="idle"){r(this,"currentState","idle"),r(this,"transitions",[{from:"idle",event:"CONNECT",to:"connecting"},{from:"connecting",event:"CONNECTION_ESTABLISHED",to:"connected"},{from:"connecting",event:"CONNECTION_FAILED",to:"failed"},{from:"connecting",event:"ERROR",to:"failed"},{from:"connected",event:"CONNECTION_ESTABLISHED",to:"connected"},{from:"connected",event:"DISCONNECT",to:"disconnected"},{from:"failed",event:"DISCONNECT",to:"disconnected"},{from:"disconnected",event:"RECONNECT",to:"connecting"},{from:"failed",event:"RECONNECT",to:"connecting"},{from:"connected",event:"CHANNEL_CHANGE_START",to:"connected"},{from:"connected",event:"CHANNEL_CHANGE_COMPLETE",to:"connected"},{from:"connecting",event:"ERROR",to:"failed"},{from:"connected",event:"ERROR",to:"failed"},{from:"disconnected",event:"ERROR",to:"failed"}]),r(this,"callbacks",{}),this.currentState=e}getState(){return this.currentState}canTransition(e){return this.transitions.some((t=>t.from===this.currentState&&t.event===e&&(!t.guard||t.guard())))}transition(e){var t,n,i,r;const s=this.transitions.find((t=>t.from===this.currentState&&t.event===e&&(!t.guard||t.guard())));if(!s)return null==(n=(t=this.callbacks).onInvalidTransition)||n.call(t,this.currentState,e),!1;const o=this.currentState;return this.currentState=s.to,null==(r=(i=this.callbacks).onStateChange)||r.call(i,this.currentState,o,e),!0}setCallbacks(e){this.callbacks=e}reset(){var e,t;const n=this.currentState;this.currentState="idle",null==(t=(e=this.callbacks).onStateChange)||t.call(e,"idle",n,"DISCONNECT")}}const Se={mediaDevices:navigator.mediaDevices,RTCPeerConnection:RTCPeerConnection,webrtcSDK:null,console:console};class Ce{constructor(e={}){r(this,"dependencies"),this.dependencies={...Se,...e}}createConnection(e){const t=this.createAudioManager(),n=this.createStateMachine();return new Ee(e,{audioManager:t,stateMachine:n,dependencies:this.dependencies})}createAudioManager(){return new ve({echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0})}createStateMachine(){return new we("idle")}createPeerConnection(e){if(!this.dependencies.RTCPeerConnection)throw new Error("RTCPeerConnection not available");return new this.dependencies.RTCPeerConnection({iceServers:e.map((e=>({urls:e.urls,username:e.username,credential:e.credential})))})}createSignalingClient(e){if(!this.dependencies.webrtcSDK)throw new Error("WebRTC SDK not available");return new this.dependencies.webrtcSDK.SignalingClient({requestSigner:{getSignedURL:()=>e.url},region:e.region,role:this.dependencies.webrtcSDK.Role.VIEWER,clientId:e.clientId,channelARN:e.channelARN,channelEndpoint:e.channelEndpoint})}validateDependencies(){const e=["mediaDevices","RTCPeerConnection"];for(const t of e)if(!this.dependencies[t])throw new Error(`Required dependency missing: ${t}`)}updateDependencies(e){this.dependencies={...this.dependencies,...e}}}const Re=class e{constructor(e){r(this,"config"),r(this,"state",{loaded:!1,loading:!1,error:null}),r(this,"loadPromise",null),this.config={...e,loadTimeout:e.loadTimeout||3e4}}static getInstance(t){const n=`${t.sdkUrl}-${t.globalObjectName}`;return e.instances.has(n)||e.instances.set(n,new e(t)),e.instances.get(n)}static async preloadGlobalSDK(t){if(e.globalLoadPromise)return e.globalLoadPromise;const n=e.getInstance(t);e.globalLoadPromise=n.loadSDK();try{await e.globalLoadPromise}catch(i){throw e.globalLoadPromise=null,i}return e.globalLoadPromise}static isGloballyLoaded(e){return!!window[e]}isLoaded(){const t=e.isGloballyLoaded(this.config.globalObjectName);return t&&!this.state.loaded&&(this.state.loaded=!0),t}isLoading(){return this.state.loading}getError(){return this.state.error}async loadSDK(){if(!this.isLoaded())return this.loadPromise||(this.loadPromise=this.performSDKLoad()),this.loadPromise}async performSDKLoad(){if(!this.state.loading){this.state.loading=!0,this.state.error=null;try{const e=document.createElement("script");e.src=this.config.sdkUrl,e.async=!0;const t=new Promise(((t,n)=>{const i=setTimeout((()=>{r(),n(new Error(`SDK loading timeout after ${this.config.loadTimeout}ms`))}),this.config.loadTimeout),r=()=>{clearTimeout(i),e.removeEventListener("load",s),e.removeEventListener("error",o)},s=()=>{if(r(),window[this.config.globalObjectName])this.state.loaded=!0,t();else{const e=`SDK loaded but ${this.config.globalObjectName} not available on window object`;this.state.error=e,n(new Error(e))}},o=()=>{r();const e=`Failed to load SDK from ${this.config.sdkUrl}`;this.state.error=e,n(new Error(e))};e.addEventListener("load",s),e.addEventListener("error",o)}));document.head.appendChild(e),await t}catch(e){const t=e instanceof Error?e.message:"Unknown error loading SDK";throw this.state.error=t,e}finally{this.state.loading=!1,this.loadPromise=null}}}reset(){this.state={loaded:!1,loading:!1,error:null},this.loadPromise=null}};r(Re,"instances",new Map),r(Re,"globalLoadPromise",null);let Ae=Re;function ye(){return Ae.getInstance({sdkUrl:"https://unpkg.com/amazon-kinesis-video-streams-webrtc@2.4.1/dist/kvs-webrtc.min.js",globalObjectName:"KVSWebRTC"})}class Te{constructor(e){r(this,"config"),r(this,"connection",null),r(this,"sdkLoader"),r(this,"factory"),r(this,"currentState","idle"),r(this,"currentError",null),r(this,"currentStats",null),r(this,"callbacks",{}),this.config=e,this.sdkLoader=ye(),this.factory=new Ce}setCallbacks(e){this.callbacks=e}async connect(){if("connecting"!==this.currentState&&"connected"!==this.currentState)try{this.setState("connecting"),this.setError(null),await this.ensureSDKLoaded();const e=await this.getWebRTCConfigFromAPI();this.connection=this.factory.createConnection({deviceId:this.config.deviceId,channel:this.config.channel,clientId:this.config.clientId||this.config.deviceId,role:this.config.role||"VIEWER",enableStats:this.config.enableStats??!0,statsInterval:this.config.statsInterval||2e3,provider:this,webrtcConfig:e,onStateChange:e=>this.setState(e),onError:e=>this.setError(e),onStreamReceived:e=>this.handleStreamReceived(e),onStatsUpdate:e=>this.handleStatsUpdate(e)}),await this.connection.connect()}catch(e){const t=e instanceof Error?e:new Error("Connection failed");throw this.setError(t),this.setState("failed"),t}}async disconnect(){try{this.connection&&(await this.connection.disconnect(),this.connection=null);try{await he({psn:this.config.deviceId})}catch(e){}this.currentStats=null,this.setState("disconnected")}catch(e){this.setState("disconnected")}}async changeChannel(e){if(e!==this.config.channel&&"connected"===this.currentState)try{const t={front:"1",rear:"2",interior:"3",exterior:"4"}[e]||"1";await ue({psn:this.config.deviceId,param1:t}),this.config.channel=e}catch(t){throw new Error(`Failed to change channel: ${t instanceof Error?t.message:"Unknown error"}`)}}getState(){return this.currentState}getStats(){return this.currentStats}getError(){return this.currentError}getLocalAudioStream(){return this.connection?this.connection.getLocalAudioStream():null}updateConfig(e){this.config={...this.config,...e}}destroy(){this.connection&&(this.connection.destroy(),this.connection=null),this.callbacks={},this.currentStats=null,this.setState("idle")}setFactoryDependencies(e){this.factory.updateDependencies(e)}async startTwoWayAudio(e){try{const i=await me({psn:e,tokenType:"web"});if("busy"===i.status)throw new Error("Two-way audio is busy. Another user is currently using audio communication.");if(!this.connection)throw new Error("No WebRTC connection available");try{await this.connection.startTwoWayAudio()}catch(t){try{await fe({psn:e,tokenType:"web"})}catch(n){}throw t}return i.status||"free"}catch(t){const e=`Failed to start two-way audio: ${t instanceof Error?t.message:"Unknown error"}`;throw new Error(e)}}async stopTwoWayAudio(e){try{if(this.connection)try{await this.connection.stopTwoWayAudio()}catch(t){}return(await fe({psn:e,tokenType:"web"})).status||"free"}catch(t){const e=`Failed to stop two-way audio: ${t instanceof Error?t.message:"Unknown error"}`;throw new Error(e)}}setLocalAudioEnabled(e){this.connection&&this.connection.setLocalAudioEnabled(e)}async ensureSDKLoaded(){if(this.sdkLoader.isLoaded())this.updateFactoryWithLoadedSDK();else{if(this.sdkLoader.isLoading())return await this.sdkLoader.loadSDK(),void this.updateFactoryWithLoadedSDK();if(await this.sdkLoader.loadSDK(),this.sdkLoader.getError())throw new Error(`Failed to load WebRTC SDK: ${this.sdkLoader.getError()}`);this.updateFactory